何时使用属性和方法?

时间:2009-07-30 21:03:38

标签: c# .net coding-style

我是来自C ++的.NET世界的新手,我正在努力更好地理解属性。我注意到在.NET框架中,Microsoft使用了所有地方的属性。使用属性而不是创建get / set方法是否有优势?当一个人应该使用属性时,是否有一般指南(以及命名约定)?

14 个答案:

答案 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)

属性不仅仅是语法糖 - 如果你需要创建对象关系映射(Linq2SqlLinq2Entities),它们很重要,因为它们的行为就像变量一样可以隐藏对象关系映射(持久性)的实现细节。还可以在属性的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; }
}

您可以使用实体集ProductsCategories以及相关的类ProductCategory,就像它们是包含变量的普通对象一样:您可以读取和写入它们它们的行为就像普通变量一样。但是你也可以在Linq查询中使用它们,坚持它们(将它们存储在数据库中并检索它们)。 注意也可以使用annotations(C#属性)来定义主键是多么容易(在此示例中,ProductIDProduct的主键)。

虽然属性用于定义数据库中存储的数据的表示,但实体集类中定义了一些方法 >它控制持久性:例如,方法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();