【问题标题】:ReferenceEquals on struct after C#7C#7 之后结构上的 ReferenceEquals
【发布时间】:2018-07-09 07:01:19
【问题描述】:

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

示例代码:

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 引用?

【问题讨论】:

标签: struct c#-7.0


【解决方案1】:

看看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 方法。因为 ref 结构不允许装箱,所以您将无法调用这两个基本方法。

还要注意Compile time enforcement of safety for ref-like types

一个 ref struct 类型的值不能被装箱:

[...] 在 object 或 System.ValueType 中声明但未在 ref struct 类型中被覆盖的实例方法不能被该 ref struct 类型的接收者调用。

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

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

【讨论】:

  • 我认为问题在于,那个 object.ReferenceEquals(val3, val1) 正在装箱我的价值观,所以我真正应该称之为struct.ReferenceEquals(ref val3, ref val1) - 如果存在类似的东西......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-11-17
  • 1970-01-01
  • 2021-04-11
  • 1970-01-01
  • 1970-01-01
  • 2011-07-04
  • 1970-01-01
相关资源
最近更新 更多