属性和参考

时间:2021-01-06 14:44:28

标签: c# properties ref

考虑具有任何类型的私有字段 A(例如 _data)和属性 int 的类 Data 来处理该字段:

public class A
{
    private int _data;

    public int Data
    {
        get => _data;
        set => _data = value;
    }

    // Constructor is redudant, I created that for testing purposes...
    public A(int data)
    {
        _data = data;
    }
}

现在考虑具有相同私有字段 B 和属性 _data 的类 Data,它只返回对我们字段的引用:

public class B
{
    private int _data;

    public ref int Data
    {
        get => ref _data;
    }

    // Constructor is redudant, I created that for testing purposes...
    public B(int data)
    {
        _data = data;
    }
}

现在我找不到答案的问题:如果没有 {{1},为什么我能够在类 _data 的实例中更改 B 的值} set 的修饰符?

Data

它是否像 C/C++ 中的 pointers 那样工作,并且编译器知道这个属性只是一个 指针,所以它会自动将值分配给这个指针指向的内容(没有任何特殊的运算符和/或演员)或者我遗漏了什么?

我无法在 B b = new B(50); // This line doesn't produce any warnings or errors b.Data = 100; Console.WriteLine(b.Data == 100); // True 上找到答案(搜索 docs.microsoft.comProperties),因此不胜感激。

1 个答案:

答案 0 :(得分:4)

确实,使用 ref 我们可以得到一个引用并且我们可以改变它的值。

考虑这个代码:

A a = new A();
B b = new B();

a.Data = 100;
b.Data = 200;

IL 生成的代码是:

// A a = new A();
IL_0001: newobj instance void ConsoleApp.A::.ctor()
IL_0006: stloc.0

// B b = new B();
IL_0007: newobj instance void ConsoleApp.B::.ctor()
IL_000c: stloc.1

// a.Data = 100;
IL_000d: ldloc.0
IL_000e: ldc.i4.s 100
IL_0010: callvirt instance void ConsoleApp.A::set_Data(int32)

// b.Data = 200;
IL_0016: ldloc.1
IL_0017: callvirt instance int32& ConsoleApp.B::get_Data()
IL_001c: ldc.i4 200
IL_0021: stind.i4
  • 使用 setter,我们调用一个方法,并将 int32 value 作为参数传递。

  • 使用 by ref getter,我们得到了一个整数的引用:int32&

编译器说,通过 ref 具有 getter 的属性不能具有 setter。

因为它既无用又多余。

因此,处理只能在 by ref getter 中完成,例如根据某些条件返回一个或另一个引用:

<块引用> CurrentColor 控件的

Enabled 将返回 ColorEnabled,否则返回 ColorDisabled


a.Data = 100 转录的原生 x86 机器代码是:

mov         rcx,qword ptr [rbp+40h]  
mov         edx,64h  
cmp         dword ptr [rcx],ecx  
call        00007FF7E93B0568  

对于 b.Data = 200 是:

mov         rcx,qword ptr [rbp+38h]  
cmp         dword ptr [rcx],ecx  
call        00007FF7E93B0580  
mov         qword ptr [rbp+20h],rax  
mov         rax,qword ptr [rbp+20h]  
mov         dword ptr [rax],0C8h  
相关问题