Есть ли способ сравнить 2 ref структуры по ссылке? - PullRequest
0 голосов
/ 03 февраля 2019

Недавно я бродил, можно ли сравнить структуры по ссылке.Поскольку чтение структурной переменной создает копию этой переменной, сравнение стандартных структур по ссылке кажется невозможным.Однако использование C # 7 ref s будет иметь больше смысла.

Я определил 4 переменные

MyStruct foo = new MyStruct(){SomeInt = 1};
ref MyStruct refFoo = ref foo;

MyStruct bar = new MyStruct() { SomeInt = 2 };
ref MyStruct refBar = ref foo;

Учитывая, что MyStruct является стандартной структурой

struct MyStruct
{
    public int SomeInt { get; set; }
}

Когда я пытаюсьэто: var comparison1 = ReferenceEquals(refFoo, refBar);, я получаю предупреждение о том, что значение всегда ложно, так как я передаю типы значений.

Если я использую C # 7 ref struct вместо

ref struct MyStruct
{
    public int SomeInt { get; set; }
}

Когда я пытаюсь это сделать: var comparison1 = ReferenceEquals(refFoo, refBar);, я получаю ошибку компиляции , говорящую, что MyStruct нельзя назначить типу параметра object.То же самое, если я попытаюсь: var comparison1 = ReferenceEquals(foo, bar);

Последний случай, когда MyStruct равен ref struct, но переменные refFoo и refBar объявлены без ref.(Я получаю ту же ошибку, что и во втором случае)

static void Main(string[] args)
{
    MyStruct foo = new MyStruct(){SomeInt = 1};
    MyStruct refFoo = foo;

    MyStruct bar = new MyStruct() { SomeInt = 2 };
    MyStruct refBar = foo;

    var comparison1 = ReferenceEquals(refFoo, refBar);

}

ref struct MyStruct
{
    public int SomeInt { get; set; }
}
  • Итак, есть ли какой-нибудь хитрый способ сравнения структур по ссылке?
  • Дополнительный вопрос: почему только второйи 3-й пример дает мне ошибку компиляции?

1 Ответ

0 голосов
/ 04 февраля 2019

var comparison1 = ReferenceEquals(refFoo, refBar);, я получаю предупреждение о том, что значение всегда ложно, так как я передаю типы значений

Каждое из значений будет упаковано в квадрат, поэтому результат всегда будет ложным.

var comparison1 = ReferenceEquals(refFoo, refBar);, я получаю ошибку компиляции, говорящую, что MyStruct не может быть назначен объекту типа параметра.То же самое, если я попытаюсь: var comparison1 = ReferenceEquals(foo, bar);

ref не может быть упакован или распакован (как писал @PetSerAl).

Последний случай - это когда MyStructэто ref struct, но переменные refFoo и refBar объявляются без ref.(Я получаю ту же ошибку, что и во втором случае)

То же, что и выше.

Бонусный вопрос: почему только 2-й и 3-й примеры дают мне ошибку компиляции?

Я уверен, теперь вы понимаете.

Итак, есть ли какой-нибудь хитрый способ сравнить структуры по ссылке?

Если вызначит сравнивать адреса, вот несколько примеров:

class Program
{
    struct Struct { public int Value { get; set; } }
    ref struct RefStruct { public int Value { get; set; } }

    static unsafe void Main(string[] args)
    {
        var @struct = new Struct { Value = 5 };
        var struct2 = @struct;
        ref Struct struct3 = ref @struct;
        Struct* p = &@struct;
        Struct* p2 = &struct2;
        Console.WriteLine($"struct  address is: {(int)p} struct  value is {p->Value}");
        Console.WriteLine($"struct2 address is: {(int)p2} struct2 value is {p2->Value}");
        fixed (Struct* p3 = &struct3)
        {
            Console.WriteLine($"struct3 address is: {(int)p3} struct3 value is {p3->Value}");
        }

        Console.WriteLine();
        Console.WriteLine($"struct and struct2 Unsafe.AreSame? {Unsafe.AreSame(ref @struct, ref struct2)}");
        Console.WriteLine($"struct and struct3 Unsafe.AreSame? {Unsafe.AreSame(ref @struct, ref struct3)}");
        Console.WriteLine();

        var structAsPointer = Unsafe.AsPointer(ref @struct);
        var struct2AsPointer = Unsafe.AsPointer(ref struct2);
        var struct3AsPointer = Unsafe.AsPointer(ref struct3);
        Console.WriteLine($"struct AsPointer and struct2 AsPointer are same? {structAsPointer == struct2AsPointer}");
        Console.WriteLine($"struct AsPointer and struct3 AsPointer are same? {structAsPointer == struct3AsPointer}");
        Console.WriteLine();

        var refStruct = new RefStruct { Value = 7 };
        var refStruct2 = refStruct;
        RefStruct* p4 = &refStruct;
        RefStruct* p5 = &refStruct2;
        Console.WriteLine($"refStruct  address is: {(int)p4}, refStruct  value is: {p4->Value}");
        Console.WriteLine($"refStruct2 address is: {(int)p5}, refStruct value is: {p5->Value}");

        ref RefStruct refStruct3 = ref refStruct;
        fixed (RefStruct* p6 = &refStruct3)
        {
            Console.WriteLine($"refStruct3 address is: {(int)p6}, refStruct3 value is: {p6->Value}");
            Console.WriteLine();
            Console.WriteLine($"refStruct and refStruct2 are same? {&refStruct == &refStruct2}");
            Console.WriteLine($"refStruct and refStruct3 are same? {&refStruct == p6}");
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...