C#:指定自动属性时会发生什么情况?

C#:指定自动属性时会发生什么情况?,c#,properties,C#,Properties,我了解到,在C#中有一个叫做autoproperty的东西,如果我声明一个变量,它通常由编译器自动生成,如: 公共列表myList{get;set;} public class MyClass { private List<int> myList; public List<int> MyList { get { return this.myList; } set

我了解到,在C#中有一个叫做autoproperty的东西,如果我声明一个变量,它通常由编译器自动生成,如: 公共列表myList{get;set;}

public class MyClass
{

   private List<int> myList;
   public List<int> MyList
   {
       get
       {
           return this.myList;
       }
       set
       {
           this.myList = value;
       }
   }
}
公共类MyClass
{
私人名单;
公共列表列表
{
得到
{
返回此.myList;
}
设置
{
this.myList=值;
}
}
}
它允许我访问变量,如:

   List<int> a = myInstance.MyList;
List a=myInstance.MyList;
所以它像函数一样工作,但像普通对象一样被调用。 但是在一个项目上真正分配的是什么呢?对象myList上是否分配了“深层链接”,或者get函数上是否分配了类似“函子”的内容? 我的意思是,如果我使用a,get函数每次都会被调用吗


我问这个问题的原因是:如果我在多线程情况下使用这个函数,在get和set函数中对对象进行一些锁定,我不想绕过锁定。所以,如果我首先将myList指定给一个,然后使用它,它将不再被锁定?我说得对吗?

属性的名称最好是
List getValue()
setValue(List value)
函数对。有一些次要属性:

  • 他们在沉思中出现
  • 它们可以在接口/抽象类中声明
  • 它们像字段一样使用,但在极少数情况下除外(out和ref参数)
但总的来说,这就是他们的全部

自动实现项目与手动项目相同,只是backingfield没有名称(您可以在代码中使用),因此没有机会意外访问backingfield

最重要的属性规则之一是不写支持字段,尤其是在类代码中。只是降低外壳,它不起作用。我记不清我是多么频繁地这么快地编码,大写字母不起作用。为实现可靠的命名,请在支持字段中添加下划线<代码>\u MyList和
MyList
很难混淆
MyList
MyList
很容易混淆

但是
a
上真正分配的是什么

a
的类型是
List
,列表是引用类型,因此变量包含对列表的引用C#不会对你撒谎。变量的类型就是变量的类型

它的工作原理类似于函数,但其调用方式类似于普通对象

这句话毫无意义,它向我表明你对C#的工作原理有些误解。“对象”不是“调用”的对象,除非它们是委托。听起来您混淆了属性、变量、对象和委托了解这些东西是什么。如果你不知道所有部件的正确名称,就很难在C#编程中取得成功

我想你想说的是,属性是一个成员,它像字段一样被访问,但是属性的读写是作为对成员访问方法的调用来实现的

我的意思是,如果我使用
a
,是否每次都会再次调用get函数

您可以自己尝试回答这个问题:

myInstance.MyList = new List<int> { 10, 20, 30 };
List<int> a = myInstance.MyList;
myInstance.MyList = new List<int> { 100, 200, 300 };
Console.WriteLine(a[0]);
myInstance.MyList=新列表{10,20,30};
列表a=myInstance.MyList;
myInstance.MyList=新列表{100200300};
Console.WriteLine(a[0]);
如果
a
再次获取属性,则该属性应为100。如果没有,则应为10。对将会发生的事情做出预测,然后尝试一下,看看你是否正确

如果我在多线程情况下使用它,并在get和set函数中锁定对象,我不想绕过锁定。因此,如果我首先将
MyList
分配给
a
,然后使用它,它将不再被锁定?我说得对吗

对。我将借此机会指出,制作公开必须锁定的对象的公共接口是一种极为糟糕的编程实践。更好的选择是:

  • 不要编写多线程程序。要把它们弄对真的很难
  • 如果必须,请不要编写跨线程共享内存的多线程程序
  • 如果必须共享内存,请始终使用线程安全集合

myInstance.MyList
分配给
a
时,调用
MyList
get属性,该属性将引用
MyList
复制到
a
中。如果您随后使用
a
,您将直接使用私有
myList
引用的列表。只有在实际调用get属性时,才能通过它

这基本上失去了myList的私有性。如果要强制调用方通过执行锁定等操作的函数,则必须为要允许的操作编写函数,如添加到列表中,而不向调用方公开实际列表


对于线程安全操作,无需在C#中执行此操作-您应该使用免费实现这些操作的。

否,它绝对不会将对字段的引用放入变量中。它将字段的值放入变量中,该值是一个引用!非常非常重要的是,你要理解其中的区别。这个答案的第一段中几乎没有什么是正确的。我们可以在C#7中得到一个字段的引用:
类C{private int f;public ref int M()=>ref this.f;}
,现在我们得到了一个字段的引用。但这与引用类型字段的内容大不相同。感谢Eric Lippert指出我的错误语言,我已编辑以更正该错误。我确实理解其中的区别,只是解释得不好。