C#:分配自动属性时会发生什么?

时间:2018-11-20 21:30:34

标签: c# properties

我了解到,在C#中有一个称为自动属性的东西,如果我声明了以下变量,它通常由编译器自动生成: 公开清单myList {get;组; }

public class MyClass
{

   private List<int> myList;
   public List<int> MyList
   {
       get
       {
           return this.myList;
       }
       set
       {
           this.myList = value;
       }
   }
}

它使我可以像这样访问变量:

   List<int> a = myInstance.MyList;

因此,它像函数一样工作,但被称为普通对象。 但是,什么是真正分配的?是否在对象myList上分配了“深层链接”,或者在get函数上分配了诸如“ functor”之类的东西? 我的意思是,如果我使用a,是否每次都会再次调用get函数?

我问的原因:如果我在多线程的情况下使用它,并且在get和set函数中对对象进行了一些锁定,则我不想绕过锁定。因此,如果我先在a上分配myList然后使用它,它将不再被锁定?我说的对吗?

3 个答案:

答案 0 :(得分:4)

  

但是在a上真正分配了什么?

a的类型为List<int>,列表是引用类型,因此变量包含对列表的引用。 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]);

如果a再次获取该属性,则该属性应为100。否则,该属性应为10。对将要发生的情况进行预测,然后尝试一下,看看您是否正确。

  

如果我在多线程的情况下使用此方法,并且在get和set函数中对对象进行了一些锁定,则我不想绕过锁定。因此,如果我先将MyList分配给a,然后再使用它,它将不再被锁定吗?我说的对吗?

是的。我将借此机会指出,创建公开接口以公开必须锁定的对象是非常糟糕的编程习惯。更好的选择是:

  • 请勿编写多线程程序。很难使他们正确。
  • 如果必须的话,不要编写跨线程共享内存的多线程程序。
  • 如果必须共享内存,请始终使用线程安全集合

答案 1 :(得分:0)

属性最好命名为List<int> getValue()setValue(List<int> value)函数对。有一些次要属性:

  • 它们出现在反射上
  • 它们可以在接口/抽象类中声明
  • 它们像字段一样使用,除了极少数情况(out和ref参数)之外

但是总的来说,这就是他们的全部。

自动实现属性与手动属性相同,只是后备字段没有名称(您可以在代码中使用),因此偶然访问后备字段的机会为零。

具有属性的最重要规则之一是不要编写Backing字段,尤其是在类代码中。只是较低的外壳它不起作用。我记不清我编码的频率有多快,大写字母没有粘住。为了可靠的命名,请在背景字段后面加上下划线。 _MyListMyList很难混淆。 MyListmyList很容易混淆。

答案 2 :(得分:0)

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

这基本上失去了myList的私密性。如果要强制调用者使用诸如锁定之类的函数,则必须为要允许的操作编写函数,例如添加到列表中,而不会将实际的列表暴露给调用者。

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