在C#中,是什么使字段与属性不同?何时应该使用字段而不是属性?
当前回答
这里的第二个问题,“什么时候应该使用字段而不是属性?”,在另一个答案中只简短地提到了这个问题,也有点像这个问题,但没有太多细节。
总的来说,所有其他答案都是关于良好设计的一针见血的:比起暴露字段,更喜欢暴露财产。虽然你可能不会经常说“哇,想象一下,如果我把这里变成了一块地而不是一块地,情况会变得多么糟糕”,但想到你会说“哇!谢天谢地,我在这里用了一块土地而不是一处地”的情况,那就难得多了
但与财产相比,字段有一个优点,那就是它们可以用作“ref”/“out”参数。假设您有一个具有以下签名的方法:
public void TransformPoint(ref double x, ref double y);
假设您希望使用该方法来转换如下创建的数组:
System.Windows.Point[] points = new Point[1000000];
Initialize(points);
因为X和Y是财产,所以我认为这是最快的方法:
for (int i = 0; i < points.Length; i++)
{
double x = points[i].X;
double y = points[i].Y;
TransformPoint(ref x, ref y);
points[i].X = x;
points[i].Y = y;
}
这会很好的!除非你的测量结果证明了这一点,否则没有理由大惊小怪。但我认为,从技术上来说,它并不能保证像这样快:
internal struct MyPoint
{
internal double X;
internal double Y;
}
// ...
MyPoint[] points = new MyPoint[1000000];
Initialize(points);
// ...
for (int i = 0; i < points.Length; i++)
{
TransformPoint(ref points[i].X, ref points[i].Y);
}
我自己进行了一些测量,带字段的版本与带财产的版本(.NET 4.6、Windows 7、x64、发布模式、未附加调试程序)相比,大约需要61%的时间。TransformPoint方法的成本越高,差异就越不明显。若要自己重复此操作,请将第一行注释掉,并将其未注释掉。
即使上述方法没有性能优势,但在其他地方使用ref和out参数可能会有好处,例如在调用Interlocked或Volatile方法家族时。注意:如果这对您来说是新的,Volatile基本上是一种获得Volatile关键字提供的相同行为的方法。因此,就像volatile一样,它并没有像名字所暗示的那样神奇地解决所有线程安全问题。
我当然不想让人觉得我在提倡你说“哦,我应该开始公开字段,而不是财产。”关键是,如果你需要在调用中定期使用这些成员来接受“ref”或“out”参数,尤其是在可能是简单值类型的东西上,它不太可能需要财产的任何增值元素,那么可以进行一个参数。
其他回答
其他信息:默认情况下,get和set访问器与属性本身一样可访问。通过对访问器应用更严格的访问修饰符,可以分别控制/限制访问器的可访问性(对于get和set)。
例子:
public string Name
{
get
{
return name;
}
protected set
{
name = value;
}
}
这里get仍然是公共访问的(因为属性是公共的),但set是受保护的(一个更受限制的访问说明符)。
来自维基百科——面向对象编程:
面向对象编程(OOP)是一种基于“对象”概念的编程范式,“对象”是以字段形式包含数据的数据结构,通常称为属性;和代码,以过程的形式,通常称为方法。(添加强调)
财产实际上是对象行为的一部分,但其设计是为了给对象的消费者提供使用对象数据的幻觉/抽象。
当您希望您的私有变量(字段)可以被其他类中的类对象访问时,您需要为这些变量创建财产。
例如,如果我的变量名为“id”,而“name”是私有的但可能存在这样的情况,即类外部的读/写操作需要此变量。在这种情况下,属性可以帮助我根据为属性定义的get/set来读取/写入该变量。属性可以是readonly/writeonly/readwriteboth。
这是演示
class Employee
{
// Private Fields for Employee
private int id;
private string name;
//Property for id variable/field
public int EmployeeId
{
get
{
return id;
}
set
{
id = value;
}
}
//Property for name variable/field
public string EmployeeName
{
get
{
return name;
}
set
{
name = value;
}
}
}
class MyMain
{
public static void Main(string [] args)
{
Employee aEmployee = new Employee();
aEmployee.EmployeeId = 101;
aEmployee.EmployeeName = "Sundaran S";
}
}
财产封装字段,从而使您能够对要设置或检索的值执行附加处理。如果您不需要对字段值进行任何预处理或后处理,那么使用财产通常是过分的。
面向对象的编程原则表明,类的内部工作应该对外界隐藏。如果公开一个字段,本质上就是公开类的内部实现。因此,我们用财产(Properties)(或Java中的方法)包装字段,使我们能够在不破坏代码的情况下更改实现。考虑到我们可以在Property中放置逻辑,还允许我们在需要时执行验证逻辑等。C#有一个可能令人困惑的自动属性概念。这允许我们简单地定义Property,而C#编译器将为我们生成私有字段。
public class Person
{
private string _name;
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
public int Age{get;set;} //AutoProperty generates private field for us
}
推荐文章
- 实体框架核心:在上一个操作完成之前,在此上下文中开始的第二个操作
- 如何为构造函数定制Visual Studio的私有字段生成快捷方式?
- 如何使用JSON确保字符串是有效的JSON。网
- AppSettings从.config文件中获取值
- 通过HttpClient向REST API发布一个空体
- 如何创建类属性?
- 如何检查IEnumerable是否为空或空?
- 自动化invokerrequired代码模式
- 在c#代码中设置WPF文本框的背景颜色
- 在c#中,什么是单子?
- c#和Java中的泛型有什么不同?和模板在c++ ?
- c#线程安全快速(est)计数器
- 如何将此foreach代码转换为Parallel.ForEach?
- 如何分裂()一个分隔字符串到一个列表<字符串>
- 如何转换列表<字符串>列表<int>?