【问题标题】:Is there a way to compare 2 ref structs by reference?有没有办法通过引用比较 2 个 ref 结构?
【发布时间】:2019-06-27 14:30:54
【问题描述】:

最近我在徘徊是否可以通过引用比较结构。由于读取结构变量会创建该变量的副本,因此通过引用比较标准结构似乎是不可能的。但是使用 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; }
}
  • 那么,是否有一些偷偷摸摸的方法来通过引用比较结构?
  • 额外问题:为什么只有第 2 和第 3 个示例给我一个汇编 错误?

【问题讨论】:

  • 为什么只有第二个例子给我一个编译错误?因为ref struct不能装箱。
  • @PetSerAl 不知道。这就是我要问的部分内容:)
  • 按照我的理解,ref structs 只需要在堆栈上,您无法获得对它的引用,就像您无法获得对堆栈分配数组的引用一样。这里的区别是编译器没有暴露幕后存在的指针。
  • @JeffMercado 谢谢,这可以解释“bouns 问题”。

标签: c# c#-7.2


【解决方案1】:

var comparison1 = ReferenceEquals(refFoo, refBar);,我收到警告说该值始终为 false,因为我正在传递值类型

每个值都会被装箱,所以结果总是假的。

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

ref 不能装箱或拆箱(就像@PetSerAl 写的那样)。

最后一种情况是 MyStruct 是 ref struct,但是 refFoo 和 refBar 变量声明时没有 ref。 (我得到与第二种情况相同的错误)

同上。

额外问题:为什么只有第二个和第三个示例给我一个编译错误?

我相信你现在明白了。

那么,有没有一些偷偷摸摸的方法来通过引用比较结构?

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

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

【讨论】:

    猜你喜欢
    • 2021-05-21
    • 2021-09-01
    • 2023-03-10
    • 1970-01-01
    • 1970-01-01
    • 2013-07-09
    • 2014-07-28
    相关资源
    最近更新 更多