我是来自C ++的.NET世界的新手,我正在努力更好地理解属性。我注意到在.NET框架中,Microsoft使用了所有地方的属性。使用属性而不是创建get / set方法是否有优势?当一个人应该使用属性时,是否有一般指南(以及命名约定)?
答案 0 :(得分:12)
它是纯粹的语法糖。在后端,它被编译为普通的get和set方法。
因为惯例而使用它,并且它看起来更好。
有些指导原则是,当它具有抛出异常或出错的高风险时,请不要使用属性,而应使用明确的getter / setter。但一般来说,即使这样,他们也会被使用。
答案 1 :(得分:7)
属性是获取/设置方法;简单地说,它将它们形式化为单个概念(用于读取和写入),允许(例如)针对属性的元数据,而不是单个成员。例如:
[XmlAttribute("foo")]
public string Name {get;set;}
这是一对get / set方法,但附加元数据适用于两者。它也是,IMO,简单易用:
someObj.Name = "Fred"; // clearly a "set"
DateTime dob = someObj.DateOfBirth; // clearly a "get"
我们没有重复我们正在进行获取/设置的事实。
另一个好处是它允许对属性(上面的“Name”)进行简单的双向数据绑定,而不依赖于任何魔术模式(除了编译器保证的那些)。
答案 2 :(得分:6)
有一整本书专门回答这些问题:来自Addison-Wesley的框架设计指南。有关何时选择财产与方法的建议,请参阅第5.1.3节。
本书的大部分内容也可以在MSDN上找到,但我觉得把它放在桌面上很方便。
答案 3 :(得分:4)
考虑阅读Choosing Between Properties and Methods。它有很多关于.NET设计指南的信息。
答案 4 :(得分:2)
属性是获取/设置方法
答案 5 :(得分:2)
设置属性并获取方法,就像这里的人已经解释过的那样,但是使用它们的想法是使这些方法成为唯一使用私有值的方法(例如,处理验证)。
应该针对属性完成整个其他逻辑,但是在处理操作(属性)的左侧和右侧的值时可以处理的事情总是更容易处理,而不必认为它是一种方法
我个人认为这是属性背后的主要理念。
答案 6 :(得分:2)
我一直认为属性是类的名词,其中方法是动词......
答案 7 :(得分:2)
首先,命名约定是:使用 PascalCase 作为属性名称,就像使用方法一样。此外,属性不应包含非常复杂的操作。这些应该用方法保存。
在OOP中,您可以将对象描述为具有属性和功能。你在设计课时这样做。考虑设计一辆汽车。功能的示例可以是移动某处或激活刮水器的能力。在你的课堂上,这些都是方法。属性将是给定时刻汽车内的乘客数量。如果没有属性,您将有两种方法来实现该属性:
公开变量:
// class Car
public int passengerCount = 4;
// calling code
int count = myCar.passengerCount;
这有几个问题。首先,它不是车辆的真正属性。您必须更新Car类内部的值,使其代表车辆的真实状态。其次,变量是公开的,也可以写入。
第二个变体是使用的一个widley,例如。 G。在Java中,您没有c#中的属性:
使用方法封装值,并可能先执行一些操作。
// class Car
public int GetPassengerCount()
{
// perform some operation
int result = CountAllPassengers();
// return the result
return result;
}
// calling code
int count = myCar.GetPassengerCount();
通过这种方式,您可以解决公共变量的问题。通过询问乘客人数,您可以确保在回答之前获得最新结果。此外,您无法更改该值,因为该方法不允许它。但问题是,您确实希望乘客数量成为一个属性,而不是您汽车的功能。
第二种方法不一定是错的,它只是读得不对。这就是为什么有些语言包含使属性看起来像变量的方法,即使它们像幕后方法一样工作。例如,Actionscript还包括定义将在调用代码中以变量样式访问的方法的语法。
请记住,这也带来了责任。调用用户将期望它的行为类似于属性,而不是函数。因此,如果只是询问一辆车有多少乘客需要20秒加载,那么你可能应该用一个真正的方法打包,因为调用者希望函数花费的时间比访问属性要长。
编辑: 我几乎忘记提到这一点:在设置变量之前实际执行某些检查的能力。通过使用公共变量,您基本上可以在其中写入任何内容。 setter方法或属性使您有机会在实际保存之前对其进行检查。
答案 8 :(得分:1)
属性只是节省了一些时间来编写与get / set方法一起使用的样板文件。
话虽这么说,很多.NET的东西处理属性的方式不同 - 例如,Grid会自动显示属性但不会显示具有相同功能的函数。
这很方便,因为您可以为不想显示的内容创建get / set方法,并为想要显示的内容创建属性。
答案 9 :(得分:0)
编译器实际为您定义的每个属性发出get_MyProperty和set_MyProperty方法。
答案 10 :(得分:0)
虽然它并不是一个硬性规则,正如其他人所指出的那样,属性在幕后实现为Get / Set对 - 通常是Properties表面封装/保护状态数据而Method(又称程序或函数)做好工作并完成工作的成果。
因为这样的方法会经常采用他们可能只是消费的论据,但也可能会以改变的状态返回,或者由于完成的工作而产生新的对象或价值。
一般来说 - 如果您需要一种控制对数据或状态的访问的方法,则属性允许实现以定义的,可验证的和优化的方式访问(允许访问限制,范围和错误检查,创建后备存储按需和避免冗余设置呼叫的方法。
相比之下,方法在内部和外部转换状态并产生新值,而不一定是可重复的结果。
当然,如果你发现自己在一个属性中编写程序或变形代码,你可能真的在编写一个方法。
答案 11 :(得分:0)
另请注意,属性可通过反射获得。虽然方法也是,但属性代表对象的“有趣的东西”。如果您试图显示对象属性的网格 - 比如像Visual Studio表单设计器那样 - 那么您可以使用反射来查询类的属性,遍历每个属性,并查询对象的内容值。
答案 12 :(得分:0)
以这种方式思考,Properties封装您的字段(通常标记为私有),同时为您的开发人员提供设置或获取字段值。如果需要,您甚至可以在属性的set方法中执行例行验证。
答案 13 :(得分:0)
属性不仅仅是语法糖 - 如果你需要创建对象关系映射(Linq2Sql或Linq2Entities),它们很重要,因为它们的行为就像变量一样可以隐藏对象关系映射(持久性)的实现细节。还可以在属性的getter中验证分配给它的值,并保护它不会分配不需要的值。
你不能用同样优雅的方法来做到这一点。我认为最好用一个实际的例子来证明这一点。
在他的一篇文章中,Scott Gu使用“代码优先”方法创建映射到Northwind数据库的类。一个简短的例子来自Scott的博客(稍加修改,完整的文章可以在Scott Gu的博客here上阅读):
public class Product
{
[Key]
public int ProductID { get; set; }
public string ProductName { get; set; }
public Decimal? UnitPrice { get; set; }
public bool Discontinued { get; set; }
public virtual Category category { get; set; }
}
// class Category omitted in this example
public class Northwind : DbContext
{
public DbSet<Product> Products { get; set; }
public DbSet<Category> Categories { get; set; }
}
您可以使用实体集Products
,Categories
以及相关的类Product
和Category
,就像它们是包含变量的普通对象一样:您可以读取和写入它们它们的行为就像普通变量一样。但是你也可以在Linq查询中使用它们,坚持它们(将它们存储在数据库中并检索它们)。
注意也可以使用annotations(C#属性)来定义主键是多么容易(在此示例中,ProductID
是Product
的主键)。
虽然属性用于定义数据库中存储的数据的表示,但实体集类中定义了一些方法 >它控制持久性:例如,方法Remove()
将给定实体标记为已删除,而Add()
添加给定实体,SaveChanges()
使更改成为永久性。您可以将这些方法视为操作(即您可以控制要对数据执行的操作)。
最后,我举一个例子,你可以自然地使用这些类:
// instantiate the database as object
var nw = new NorthWind();
// select product
var product = nw.Products.Single(p => p.ProductName == "Chai");
// 1. modify the price
product.UnitPrice = 2.33M;
// 2. store a new category
var c = new Category();
c.Category = "Example category";
c.Description = "Show how to persist data";
nw.Categories.Add(c);
// Save changes (1. and 2.) to the Northwind database
nw.SaveChanges();