C#7之后在结构上引用等于

时间:2018-07-09 07:01:19

标签: struct c#-7.0

从C#7.2开始,可以在结构上使用“ ref”关键字来创建嵌入式引用。如何确定两个结构变量是否指向相同的引用? ReferenceEquals始终返回false

SampleCode:

struct MyStruct
{
    public string Name { get; set; }
}

static void Main(string[] args)
{
    MyStruct val1 = new MyStruct() { Name = "Value1" };
    MyStruct val2 = new MyStruct() { Name = "Value2" };
    MyStruct val4 = new MyStruct() { Name = "New name" };

    ref var val3 = ref val1;

    val1.Name = "New name";

    Console.WriteLine("Val 1: " + val1.Name);
    Console.WriteLine("Val 2: " + val2.Name);
    Console.WriteLine("Val 3: " + val3.Name);

    Console.WriteLine("Val3 eq Val1: " + val3.Equals(val1));
    Console.WriteLine("Val3 eq Val2: " + val3.Equals(val2));
    Console.WriteLine("Val3 eq Val4: " + val3.Equals(val4));

    Console.WriteLine("Val3 ref eq Val1: " + object.ReferenceEquals(val3, val1));
    Console.WriteLine("Val3 ref eq Val2: " + object.ReferenceEquals(val3, val2));

    Console.ReadKey();
}

输出:

Val 1: New name
Val 2: Value2  
Val 3: New name
Val3 eq Val1: True
Val3 eq Val2: False
Val3 eq Val4: True
Val3 ref eq Val1: False <--- This should return true
Val3 ref eq Val2: False

那么如何在C#7中检查相同的struct引用?

1 个答案:

答案 0 :(得分:3)

看看C# 7 Series, Part 9: ref structs

  

ref struct是仅用于堆栈的值类型,

     

表示顺序结构布局;      只能用于堆栈。即方法参数和局部变量;      不能是类或普通结构的静态或实例成员;      不能是异步方法或lambda表达式的方法参数;      无法进行动态绑定,装箱,拆箱,换行或转换。

(重点是我的)

然后他继续将Equals实现为

public ref struct MyRefStruct
{
    [EditorBrowsable(EditorBrowsableState.Never)]
    public override bool Equals(object obj) => throw new NotSupportedException();

    // ...
}

有正当理由

  

请注意,我已重写了从System.Object继承的Equals,GetHashCode和ToString方法。由于引用结构不允许装箱,因此您将无法调用这两个基本方法。

请注意,Compile time enforcement of safety for ref-like types

  

引用结构类型的值可能不会被装箱:

     

[...]   在对象或System.ValueType中声明但未被引用结构类型覆盖的实例方法不能被该引用结构类型的接收者调用。

也就是说,尽管您可以实现ref struct MyEmbeddedStruct { public override bool Equals(object obj) => true; },但是您只能通过val3.Equals(/*...*/)来调用它,而不能通过object.ReferenceEquals()来调用它。而且您无法向obj提供参数Equals,因为您必须将参数装箱。

因此,您的问题的答案可能是:无法确定两个(嵌入式)结构是否指向同一引用。 (而且,当您处理两个普通结构时,这个问题一开始就没有任何意义。)