在C#中,是什么使字段与属性不同?何时应该使用字段而不是属性?
当前回答
在大多数情况下,它将是您访问的属性名,而不是变量名(字段)。原因是,在.NET中,尤其是在C#中,它被认为是保护类中的每一条数据的良好做法,无论是实例变量还是静态变量(类变量),因为它与类相关联。
使用相应的财产保护所有这些变量,这些属性允许您定义、设置和获取访问器,并在操作这些数据片段时执行验证等操作。
但在其他情况下,如Math类(System命名空间),类中内置了一些静态财产。其中一个是数学常数PI
例如数学PI
因为PI是一块定义良好的数据,我们不需要有多个PI副本,它总是相同的值。因此,静态变量有时用于在类的对象之间共享数据,但也通常用于只需要一个数据副本的常量信息。
其他回答
基本区别和一般区别是:
领域
始终给予get和set访问权限不会造成副作用(引发异常、调用方法、更改字段(获取/设置的字段除外)等)
财产
并非总是同时提供get和set访问权限CAN导致副作用
这里的第二个问题,“什么时候应该使用字段而不是属性?”,在另一个答案中只简短地提到了这个问题,也有点像这个问题,但没有太多细节。
总的来说,所有其他答案都是关于良好设计的一针见血的:比起暴露字段,更喜欢暴露财产。虽然你可能不会经常说“哇,想象一下,如果我把这里变成了一块地而不是一块地,情况会变得多么糟糕”,但想到你会说“哇!谢天谢地,我在这里用了一块土地而不是一处地”的情况,那就难得多了
但与财产相比,字段有一个优点,那就是它们可以用作“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”参数,尤其是在可能是简单值类型的东西上,它不太可能需要财产的任何增值元素,那么可以进行一个参数。
来自维基百科——面向对象编程:
面向对象编程(OOP)是一种基于“对象”概念的编程范式,“对象”是以字段形式包含数据的数据结构,通常称为属性;和代码,以过程的形式,通常称为方法。(添加强调)
财产实际上是对象行为的一部分,但其设计是为了给对象的消费者提供使用对象数据的幻觉/抽象。
这里清楚地解释了区别。然而,只是为了总结和强调:
字段封装在类内部以进行内部操作,而财产可用于将类公开给外部世界,以及共享链接中显示的其他内部操作。此外,如果您希望基于特定字段的值加载某些方法或用户控件,则属性将为您完成此操作:
例如:
您可以在asp.net页面中的用户控件下方运行,只需为aspx页面中控件的Id前缀赋值,如下所示:
useMeId.Id=5 ---call the property of user control "UseMe.ascx"
使用Me.ascx
<%@ Register Src=~/"UseMe.ascx" TagPrefix="uc" TagName="UseMe" %>
<uc:UseMe runat="Server" id="useMeId" />
UseMe.ascx.cs
private int currentId;
public int Id
{
get
{
return currentId;
}
set
{
currentId = value;
LoadInitialData(currentId);
}
}
Private void LoadinitialData(int currentIdParam)
{
//your action
}
想想看:你有一个房间和一扇门可以进入这个房间。如果你想检查谁是如何进来并保护你的房间的,那么你应该使用财产,否则他们不会是任何门,每个人都很容易进来,没有任何规定
class Room {
public string sectionOne;
public string sectionTwo;
}
Room r = new Room();
r.sectionOne = "enter";
人们很容易进入第一区,没有任何检查
class Room
{
private string sectionOne;
private string sectionTwo;
public string SectionOne
{
get
{
return sectionOne;
}
set
{
sectionOne = Check(value);
}
}
}
Room r = new Room();
r.SectionOne = "enter";
现在你检查了这个人,知道他是否有什么不好的地方
推荐文章
- net HttpClient。如何POST字符串值?
- 我如何使一个方法的返回类型泛型?
- 何时处理CancellationTokenSource?
- 如何获取正在执行的程序集版本?
- AutoMapper vs valueinjector
- 为什么控制台不。Writeline,控制台。在Visual Studio Express中编写工作?
- 什么是.NET程序集?
- 字符串不能识别为有效的日期时间“格式dd/MM/yyyy”
- 函数应该返回空对象还是空对象?
- 如何转换日期时间?将日期时间
- 如何在c#中连接列表?
- 在c#中引用类型变量的“ref”的用途是什么?
- 防止在ASP中缓存。NET MVC中使用属性的特定操作
- 转换为值类型'Int32'失败,因为物化值为空
- c#中有任何连接字符串解析器吗?