값 형식 복사 / 관리되는 메모리에서 관리되지 않는 메모리로 참조를 통해 전달되는 형식 복사
값으로 전달되는 참조 형식은 복사 또는 고정됨

 

 

'.NET > C#' 카테고리의 다른 글

Concurrency - Asynchronous Programming  (0) 2023.08.16
Concurrency (동시성)  (0) 2023.08.16
Array Marshaling  (0) 2021.10.15
Comparisons and Sorts  (0) 2021.10.15
Debugging Tips  (0) 2021.09.15

C++

HRESULT New1(int ar[10]);  
HRESULT New2(double ar[10][20]);  
HRESULT New3(LPWStr ar[10]);

C#

void New1([MarshalAs(UnmanagedType.LPArray, SizeConst=10)] int[] ar);  
void New2([MarshalAs(UnmanagedType.LPArray, SizeConst=200)] double[] ar);  
void New2([MarshalAs(UnmanagedType.LPArray,
    ArraySubType=UnmanagedType.LPWStr, SizeConst=10)] String[] ar);

C++

HRESULT New1(int ar[]);  
HRESULT New2(int ArSize, [size_is(ArSize)] double ar[]);  
HRESULT New3(int ElemCnt, [length_is(ElemCnt)] LPStr ar[]);

C#

void New1(ref int ar);
void New2(ref double ar);
void New3(ref String ar);

배열의 요소 수를 지정하는 방법

1. 배열의 요소 수가 포함된 또 다른 매개 변수 식별, 매개 변수는 위치로 식별

void New(  
    int ElemCnt,
    [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] int[] ar);

2. 배열의 크기를 상수로 정의

void New(  
    [MarshalAs(UnmanagedType.LPArray, SizeConst=128)] int[] ar);

 

구조체 내의 배열

C++

struct MyStruct {
    int values[128];
};

C#

[StructLayout(LayoutKind.Sequential)]
public struct MyStruct
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConstant = 128)] public int[] values;
}

 

 

 

struct Image {
    unsigned char* image_ptr;
    int rows;
    int cols;
};

typedef void (*pfnCallback)(bool[], const char* [], Image[], Image, int length);
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct Image
{
    public IntPtr image_ptr;
    public int rows;
    public int cols;
}

public delegate void dgCallback(
    [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.I1, SizeParamIndex = 4)] bool[] status,
    [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr, SizeParamIndex = 4)] string[] id,
    [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] Image[] img_face,
    Image img_org,
    int length);

 

 

 

 

 

 

'.NET > C#' 카테고리의 다른 글

Concurrency (동시성)  (0) 2023.08.16
Marshaling: 복사 및 고정  (0) 2021.10.15
Comparisons and Sorts  (0) 2021.10.15
Debugging Tips  (0) 2021.09.15
Equals, IEquatable<T>  (0) 2021.08.15

https://docs.microsoft.com/en-us/dotnet/standard/collections/comparisons-and-sorts-within-collections

 

Comparisons and Sorts Within Collections

Do comparisons & sorts using the System.Collections classes in .NET, which help in finding an element to remove or returning the value of a key-and-value pair.

docs.microsoft.com

Check for Equality

If the collection is generic, then items are compared for equality according to the following guidelines:

  1. If type T implements the IEquatable<T> generic interface,
    then the equality comparer is the Equals method of that interface.
  2. If type T does not implement IEquatable<T>, Object.Equals is used.

In addition, some constructor overloads for dictionary collections an IEqualityComparer<T> implementation,
which is used to compare keys for equality.

 

We recommend that you derive from the EqualityComparer<T> class instead of implementing the IEqualityComparer<T> interface, because the EqualityComparer<T> class tests for equality using the IEquatable<T>.Equals method instead of the Object.Equals method.

 

Determine Sort Order

For comparing objects, there is the concept of a default comparer and an explicit comparer.

The default comparer relies on at least one of the objects being compared to implement the IComparable interface.

For a generic collection, equality comparison is determined according to the following:

  • If type T implements the System.IComparable<T> generic interface,
    then the default comparer is the IComparable<T>.CompareTo(T) method of that interface.
  • If type T implements the non-generic System.IComparable interface,
    then the default comparer is the IComparable.CompareTo(Object) method that interface.
  • If type T doen't implement either interface,
    then there is no default comparer, and a comparer or comparison delegate must be provided explicity.

Example:

using System;
using System.Collections.Generic;

// Simple business object. A PartId is used to identify the
// type of part but the part name can change.
public class Part : IEquatable<Part>, IComparable<Part>
{
    public string PartName { get; set; }

    public int PartId { get; set; }

    public override string ToString() => 
        $"ID: {PartId}   Name: {PartName}";

    public override bool Equals(object obj) => 
        (obj is Part part)
                ? Equals(part)
                : false;

    public int SortByNameAscending(string name1, string name2) => 
        name1?.CompareTo(name2) ?? 1;

    // Default comparer for Part type.
    // A null value means that this object is greater.
    public int CompareTo(Part comparePart) =>
        comparePart == null ? 1 : PartId.CompareTo(comparePart.PartId);

    public override int GetHashCode() => PartId;

    public bool Equals(Part other) =>
        other is null ? false : PartId.Equals(other.PartId);

    // Should also override == and != operators.
}

public class Example
{
    public static void Main()
    {
        // Create a list of parts.
        var parts = new List<Part>
        {
            // Add parts to the list.
            new Part { PartName = "regular seat", PartId = 1434 },
            new Part { PartName = "crank arm", PartId = 1234 },
            new Part { PartName = "shift lever", PartId = 1634 },
            // Name intentionally left null.
            new Part { PartId = 1334 },
            new Part { PartName = "banana seat", PartId = 1444 },
            new Part { PartName = "cassette", PartId = 1534 }
        };
        
        // Write out the parts in the list. This will call the overridden
        // ToString method in the Part class.
        Console.WriteLine("\nBefore sort:");
        parts.ForEach(Console.WriteLine);

        // Call Sort on the list. This will use the
        // default comparer, which is the Compare method
        // implemented on Part.
        parts.Sort();

        Console.WriteLine("\nAfter sort by part number:");
        parts.ForEach(Console.WriteLine);

        // This shows calling the Sort(Comparison<T> comparison) overload using
        // a lambda expression as the Comparison<T> delegate.
        // This method treats null as the lesser of two values.
        parts.Sort((Part x, Part y) => 
            x.PartName == null && y.PartName == null
                ? 0
                : x.PartName == null
                    ? -1
                    : y.PartName == null
                        ? 1
                        : x.PartName.CompareTo(y.PartName));

        Console.WriteLine("\nAfter sort by name:");
        parts.ForEach(Console.WriteLine);

        /*

            Before sort:
        ID: 1434   Name: regular seat
        ID: 1234   Name: crank arm
        ID: 1634   Name: shift lever
        ID: 1334   Name:
        ID: 1444   Name: banana seat
        ID: 1534   Name: cassette

        After sort by part number:
        ID: 1234   Name: crank arm
        ID: 1334   Name:
        ID: 1434   Name: regular seat
        ID: 1444   Name: banana seat
        ID: 1534   Name: cassette
        ID: 1634   Name: shift lever

        After sort by name:
        ID: 1334   Name:
        ID: 1444   Name: banana seat
        ID: 1534   Name: cassette
        ID: 1234   Name: crank arm
        ID: 1434   Name: regular seat
        ID: 1634   Name: shift lever

         */
    }
}

 

using System;
using System.Collections.Generic;

class Program
{
    static Dictionary<Box, String> boxes;

    static void Main()
    {
        BoxSameDimensions boxDim = new BoxSameDimensions();
        boxes = new Dictionary<Box, string>(boxDim);

        Console.WriteLine("Boxes equality by dimensions:");
        Box redBox = new Box(8, 4, 8);
        Box greenBox = new Box(8, 6, 8);
        Box blueBox = new Box(8, 4, 8);
        Box yellowBox = new Box(8, 8, 8);
        AddBox(redBox, "red");
        AddBox(greenBox, "green");
        AddBox(blueBox, "blue");
        AddBox(yellowBox, "yellow");

        Console.WriteLine();
        Console.WriteLine("Boxes equality by volume:");

        BoxSameVolume boxVolume = new BoxSameVolume();
        boxes = new Dictionary<Box, string>(boxVolume);
        Box pinkBox = new Box(8, 4, 8);
        Box orangeBox = new Box(8, 6, 8);
        Box purpleBox = new Box(4, 8, 8);
        Box brownBox = new Box(8, 8, 4);
        AddBox(pinkBox, "pink");
        AddBox(orangeBox, "orange");
        AddBox(purpleBox, "purple");
        AddBox(brownBox, "brown");
    }

    public static void AddBox(Box bx, string name)
    {
        try
        {
            boxes.Add(bx, name);
            Console.WriteLine("Added {0}, Count = {1}, HashCode = {2}",
                name, boxes.Count.ToString(), bx.GetHashCode());
        }
        catch (ArgumentException)
        {
            Console.WriteLine("A box equal to {0} is already in the collection.", name);
        }
    }
}

public class Box
{
    public Box(int h, int l, int w)
    {
        this.Height = h;
        this.Length = l;
        this.Width = w;
    }
    public int Height { get; set; }
    public int Length { get; set; }
    public int Width { get; set; }
}

class BoxSameDimensions : EqualityComparer<Box>
{
    public override bool Equals(Box b1, Box b2)
    {
        if (b1 == null && b2 == null)
            return true;
        else if (b1 == null || b2 == null)
            return false;

        return (b1.Height == b2.Height &&
                b1.Length == b2.Length &&
                b1.Width == b2.Width);
    }

    public override int GetHashCode(Box bx)
    {
        int hCode = bx.Height ^ bx.Length ^ bx.Width;
        return hCode.GetHashCode();
    }
}

class BoxSameVolume : EqualityComparer<Box>
{
    public override bool Equals(Box b1, Box b2)
    {
        if (b1 == null && b2 == null)
            return true;
        else if (b1 == null || b2 == null)
            return false;

        return (b1.Height * b1.Width * b1.Length ==
                b2.Height * b2.Width * b2.Length);
    }

    public override int GetHashCode(Box bx)
    {
        int hCode = bx.Height * bx.Length * bx.Width;
        return hCode.GetHashCode();
    }
}

/* This example produces an output similar to the following:
 *
      Boxes equality by dimensions:
      Added red, Count = 1, HashCode = 46104728
      Added green, Count = 2, HashCode = 12289376
      A box equal to blue is already in the collection.
      Added yellow, Count = 3, HashCode = 43495525

      Boxes equality by volume:
      Added pink, Count = 1, HashCode = 55915408
      Added orange, Count = 2, HashCode = 33476626
      A box equal to purple is already in the collection.
      A box equal to brown is already in the collection.
 *
 */
using System;
using System.Collections;
using System.Collections.Generic;

class Program
{
    static void Main(string[] args)
    {
        List<Box> Boxes = new List<Box>();
        Boxes.Add(new Box(4, 20, 14));
        Boxes.Add(new Box(12, 12, 12));
        Boxes.Add(new Box(8, 20, 10));
        Boxes.Add(new Box(6, 10, 2));
        Boxes.Add(new Box(2, 8, 4));
        Boxes.Add(new Box(2, 6, 8));
        Boxes.Add(new Box(4, 12, 20));
        Boxes.Add(new Box(18, 10, 4));
        Boxes.Add(new Box(24, 4, 18));
        Boxes.Add(new Box(10, 4, 16));
        Boxes.Add(new Box(10, 2, 10));
        Boxes.Add(new Box(6, 18, 2));
        Boxes.Add(new Box(8, 12, 4));
        Boxes.Add(new Box(12, 10, 8));
        Boxes.Add(new Box(14, 6, 6));
        Boxes.Add(new Box(16, 6, 16));
        Boxes.Add(new Box(2, 8, 12));
        Boxes.Add(new Box(4, 24, 8));
        Boxes.Add(new Box(8, 6, 20));
        Boxes.Add(new Box(18, 18, 12));

        // Sort by an Comparer<T> implementation that sorts
        // first by the length.
        Boxes.Sort(new BoxLengthFirst());

        Console.WriteLine("H - L - W");
        Console.WriteLine("==========");
        foreach (Box bx in Boxes)
        {
            Console.WriteLine("{0}\t{1}\t{2}",
                bx.Height.ToString(), bx.Length.ToString(),
                bx.Width.ToString());
        }

        Console.WriteLine();
        Console.WriteLine("H - L - W");
        Console.WriteLine("==========");

        // Get the default comparer that
        // sorts first by the height.
        Comparer<Box> defComp = Comparer<Box>.Default;

        // Calling Boxes.Sort() with no parameter
        // is the same as calling Boxs.Sort(defComp)
        // because they are both using the default comparer.
        Boxes.Sort();

        foreach (Box bx in Boxes)
        {
            Console.WriteLine("{0}\t{1}\t{2}",
                bx.Height.ToString(), bx.Length.ToString(),
                bx.Width.ToString());
        }


        // This explicit interface implementation
        // compares first by the length.
        // Returns -1 because the length of BoxA
        // is less than the length of BoxB.
        BoxLengthFirst LengthFirst = new BoxLengthFirst();

        Comparer<Box> bc = (Comparer<Box>) LengthFirst;

        Box BoxA = new Box(2, 6, 8);
        Box BoxB = new Box(10, 12, 14);
        int x = LengthFirst.Compare(BoxA, BoxB);
        Console.WriteLine();
        Console.WriteLine(x.ToString());
    }
}

public class BoxLengthFirst : Comparer<Box>
{
    // Compares by Length, Height, and Width.
    public override int Compare(Box x, Box y)
    {
        if (x.Length.CompareTo(y.Length) != 0)
        {
            return x.Length.CompareTo(y.Length);
        }
        else if (x.Height.CompareTo(y.Height) != 0)
        {
            return x.Height.CompareTo(y.Height);
        }
        else if (x.Width.CompareTo(y.Width) != 0)
        {
            return x.Width.CompareTo(y.Width);
        }
        else
        {
            return 0;
        }
    }
}

// This class is not demonstrated in the Main method
// and is provided only to show how to implement
// the interface. It is recommended to derive
// from Comparer<T> instead of implementing IComparer<T>.
public class BoxComp : IComparer<Box>
{
    // Compares by Height, Length, and Width.
    public int Compare(Box x, Box y)
    {
        if (x.Height.CompareTo(y.Height) != 0)
        {
            return x.Height.CompareTo(y.Height);
        }
        else if (x.Length.CompareTo(y.Length) != 0)
        {
            return x.Length.CompareTo(y.Length);
        }
        else if (x.Width.CompareTo(y.Width) != 0)
        {
            return x.Width.CompareTo(y.Width);
        }
        else
        {
            return 0;
        }
    }
}

public class Box : IComparable<Box>
{
    public Box(int h, int l, int w)
    {
        this.Height = h;
        this.Length = l;
        this.Width = w;
    }
    public int Height { get; private set; }
    public int Length { get; private set; }
    public int Width { get; private set; }

    public int CompareTo(Box other)
    {
        // Compares Height, Length, and Width.
        if (this.Height.CompareTo(other.Height) != 0)
        {
            return this.Height.CompareTo(other.Height);
        }
        else if (this.Length.CompareTo(other.Length) != 0)
        {
            return this.Length.CompareTo(other.Length);
        }
        else if (this.Width.CompareTo(other.Width) != 0)
        {
            return this.Width.CompareTo(other.Width);
        }
        else
        {
            return 0;
        }
    }
}

 

 

 

'.NET > C#' 카테고리의 다른 글

Concurrency (동시성)  (0) 2023.08.16
Marshaling: 복사 및 고정  (0) 2021.10.15
Array Marshaling  (0) 2021.10.15
Debugging Tips  (0) 2021.09.15
Equals, IEquatable<T>  (0) 2021.08.15

사용자 객체 디버거 표시 속성

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    [DebuggerDisplay("k4a_quaternion_st: wxyz({w}, {x}, {y}, {z})")]
    public readonly struct k4a_quaternion_st
    {
        public readonly float w;
        public readonly float x;
        public readonly float y;
        public readonly float z;

        public k4a_quaternion_st(float w, float x, float y, float z)
        {
            this.w = w;
            this.x = x;
            this.y = y;
            this.z = z;
        }

        public static implicit operator Quaternion(k4a_quaternion_st q)
        {
            return new Quaternion(q.x, q.y, q.z, q.w);
        }

        public static implicit operator k4a_quaternion_st(Quaternion q)
        {
            return new k4a_quaternion_st(q.W, q.X, q.Y, q.Z);
        }
    }

'.NET > C#' 카테고리의 다른 글

Concurrency (동시성)  (0) 2023.08.16
Marshaling: 복사 및 고정  (0) 2021.10.15
Array Marshaling  (0) 2021.10.15
Comparisons and Sorts  (0) 2021.10.15
Equals, IEquatable<T>  (0) 2021.08.15

Equals()

public static bool ReferenceEquals(object left, object right);
public static bool Equals(object left, object right);
// 재정의하는 경우 IEquatable<T>를 구현해야 한다.
// (값에 고유의 의미 체계를 부여하기 위해 IStructuralEquality를 구현하기도 함)
public virtual bool Equals(object right);
// 주로 성능을 개선하기 위해 재정의
public static bool operator == (MyClass left, MyClass right);
  • 참조 타입의 경우, 참조 대상이 같으면 동일하다고 간주
  • 값 타입의 경우, 두 객체의 타입과 값의 내용이 일치해야만 동일한 객체로 판단
public static bool Equals(object left, object right)
{
    if (object.ReferenceEquals(left, right))
        return true;
 
    if (object.ReferenceEquals(left, null) ||
        object.ReferenceEquals(right, null))
        return false;
 
    return left.Equals(right);
}

동일성의 수학적 속성

  • 반사적 속성(reflexive property)
    • 어떤 객체든 자기 자신과는 항상 같아야 한다.
  • 대칭적 속성(symmetric property)
    • 동일성의 결과가 비교 순서와는 무관해야 한다.
  • 추이적 속성(transitive property)
    • if (a == b) and (b == c), a == c

 

IEquatable<T>

public class MyClass : IEquatable<MyClass>
{
    public override bool Equals(object other)
    {
        // C# 메서드 내에서 this는 절대 null이 될 수 없다.
        if (object.ReferenceEquals(right, null))
            return false;

        if (object.ReferenceEquals(this, other))
            return true;

        if (this.GetType() != other.GetType())
            return false;

        return this.Equals(other as MyCalss)
    }

    // IEquatable<MyClass>
    public bool Equals(MyClass other)
    {
        ;
    }
}

'.NET > C#' 카테고리의 다른 글

Concurrency (동시성)  (0) 2023.08.16
Marshaling: 복사 및 고정  (0) 2021.10.15
Array Marshaling  (0) 2021.10.15
Comparisons and Sorts  (0) 2021.10.15
Debugging Tips  (0) 2021.09.15

+ Recent posts