有没有办法通过引用比较 2 个 ref 结构?

Is there a way to compare 2 ref structs by reference?

最近我在徘徊是否可以通过引用比较结构。由于读取结构变量会创建该变量的副本,因此通过引用比较标准结构似乎是不可能的。然而,使用 C# 7 refs 会更有意义。

我定义了 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);,我收到 警告 说该值始终为 false,因为我正在传递值类型。

如果我改用 C# 7 ref struct

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

当我尝试这个:var comparison1 = ReferenceEquals(refFoo, refBar); 时,我得到一个 编译错误 MyStruct 不能分配给参数类型 object。如果我尝试同样的事情:var comparison1 = ReferenceEquals(foo, bar);

最后一种情况是 MyStructref struct,但 refFoorefBar 变量声明时没有 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; }
}

var comparison1 = ReferenceEquals(refFoo, refBar);, I get warning saying that the value is always false, since I'm passing value types

每个值都将装箱,因此结果始终为 false。

var comparison1 = ReferenceEquals(refFoo, refBar);, I get a compilation error saying that MyStruct is not assignable to parameter type object. Same thing if I try: var comparison1 = ReferenceEquals(foo, bar);

ref 无法装箱或拆箱(如@PetSerAl 所写)。

The last case is when MyStruct is ref struct, but refFoo and refBar variables are declared without ref. (I get the same error as in the 2nd case)

同上

Bonus question: Why only the 2nd and 3rd examples give me a compilation error?

相信你已经明白了。

So, is there some sneaky way to compare structs by reference?

如果你的意思是比较地址,这里有一些例子:

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}");
        }
    }
}