最近,我游荡,如果有可能通过参照比较结构。在阅读一个结构体变量创建变量的副本,通过比较参考标准结构似乎是不可能的。然而,使用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;
struct MyStruct
{
public int SomeInt { get; set; }
}
当我试试这个:var comparison1 = ReferenceEquals(refFoo, refBar);
,我得到警告说,值始终为false,因为我传递值类型。
ref struct
insteadref struct MyStruct
{
public int SomeInt { get; set; }
}
当我试试这个:var comparison1 = ReferenceEquals(refFoo, refBar);
,我得到一个编译错误说MyStruct
是不能分配给参数类型object
。如果我尝试同样的事情:var comparison1 = ReferenceEquals(foo, bar);
MyStruct
is ref struct
, but refFoo
and refBar
variables are declared without ref
. (I get the same error as in the 2nd case)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);
,我得到警告说,值始终为false,因为我传递值类型
每个值将盒装所以结果始终为false。
var comparison1 = ReferenceEquals(refFoo, refBar);
,我得到一个编译错误说MYSTRUCT是不能分配给参数类型的对象。如果我尝试同样的事情:var comparison1 = ReferenceEquals(foo, bar);
ref
不能盒装或拆箱(像@PetSerAl写)。
最后一种情况是,当MYSTRUCT是裁判结构,但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}");
}
}
}