吸气剂,制定者和属性最佳实践。 Java与C#

时间:2011-02-09 18:18:15

标签: c# java properties getter-setter

我现在正在参加一个C#课程,我正在努力寻找最佳的做事方式。我来自Java背景,因此我只熟悉Java最佳实践;我是C#新手!

在Java中,如果我有私有财产,我会这样做;

private String name;

public void setName(String name) {
   this.name = name;
}

public String getName() {
   return this.name;
}

在C#中,我发现有很多方法可以做到这一点。

我可以像Java一样:

private string name;

public void setName(string name) {
   this.name = name;
}

public string getName() {
   return this.name;
}

或者我可以这样做:

private string name;

public string Name {
   get { return name; }
   set { name = value; }
}

或者:

public string Name { get; set; }

我应该使用哪一种,每种方法涉及的警告或细微之处是什么?在创建类时,我遵循我从Java中了解的一般最佳实践(特别是阅读Effective Java)。因此,例如,我赞成不变性(仅在必要时提供setter)。我很想知道这些实践如何适应C#中提供setter和getter的各种方法;基本上,我如何将Java世界的最佳实践转换为C#?

修改

我发布这篇文章是对Jon Skeet答案的评论,但后来很久了:

如何处理非平凡的财产(即,可能会进行重要的处理和验证)?我是否仍然可以通过公共属性公开它,但是使用getset封装的逻辑?为什么我应该/我应该使用专用的setter和getter方法(带有相关的处理和验证逻辑)。

12 个答案:

答案 0 :(得分:83)

预C#6

我会使用最后一个,这是一个微不足道的财产。请注意,我将此称为 public 属性,因为getter和setter都是公共的。

使用自动实现的属性,不可变性有点痛苦 - 你不能写一个只有getter的auto-property;你最接近的是:

public string Foo { get; private set; }

这不是真的不可变的...只是在你的课外不可变。因此,您可能希望使用真正的只读属性:

private readonly string foo;
public string Foo { get { return foo; } }

您绝对不想写getName()setName()。在一些的情况下,编写Get / Set方法而不是使用属性是有意义的,特别是如果它们可能很昂贵并且您希望强调这一点。但是,您希望遵循PascalCase的.NET命名约定来获取方法,并且您不希望这样的普通属性无论如何都要用普通方法实现 - 这里的属性更加惯用。

C#6

万岁,我们终于有了适当的只读自动实现属性:

// This can only be assigned to within the constructor
public string Foo { get; }

同样,对于需要做一些工作的只读属性,您可以使用成员身体属性:

public double Area => height * width;

答案 1 :(得分:17)

如果您只需要一个存储某些数据的变量:

public string Name { get; set; }

想让它显示为只读吗?

public string Name { get; private set; }

甚至更好......

private readonly string _name;

...

public string Name { get { return _name; } }

在分配财产之前想要进行一些价值检查吗?

public string Name 
{
   get { return m_name; }
   set
   {
      if (value == null)
         throw new ArgumentNullException("value");

      m_name = value;
   }
}

一般情况下,GetXyz()和SetXyz()仅在某些情况下使用,您只需在感觉正确时使用您的肠道。一般来说,我会说我希望大多数get / set属性不包含很多逻辑,并且几乎没有任何意外的副作用。如果读取属性值需要调用服务或从用户那里获取输入以构建我正在请求的对象,那么我会将其包装到方法中,并将其称为BuildXyz(),而不是{ {1}}。

答案 2 :(得分:12)

使用C#中的属性,而不是get / set方法。它们是为了您的方便,它是惯用的。

至于你的两个C#例子,一个是另一个的语法糖。如果您需要的只是一个实例变量的简单包装器,请使用auto属性,当您需要在getter和/或setter中添加逻辑时,请使用完整版本。

答案 3 :(得分:5)

在C#favor属性中为get和/或set公开私有字段。你提到的形式是一个autoproperty,其中get和set会自动为你生成一个隐藏的枢轴支持字段。

我尽可能使用自动属性,但你不应该在C#中使用set / get方法对。

答案 4 :(得分:5)

public string Name { get; set; }

这只是auto-implemented property,在技术上与普通属性相同。编译时将创建一个支持字段。

所有属性最终都转换为函数,因此最终的实际编译实现与您在Java中使用的相同。

当您不必对支持字段执行特定操作时,请使用自动实现的属性。否则使用普通财产。当操作有副作用或计算成本高时使用get和set函数,否则使用属性。

答案 5 :(得分:5)

首先让我试着解释你写的内容:

// private member -- not a property
private string name;

/// public method -- not a property
public void setName(string name) {
   this.name = name;
}

/// public method -- not a property
public string getName() {
   return this.name;
}

// yes it is property structure before .Net 3.0
private string name;
public string Name {
   get { return name; }
   set { name = value; }
}

现在也使用这种结构,但如果你想要做一些额外的功能,它是最合适的,例如,当设置一个值时,你可以解析它以将其大写并将其保存在私有成员中以供内部使用。 / p>

使用.net framework 3.0

// this style is introduced, which is more common, and suppose to be best
public string Name { get; set; }

//You can more customize it
public string Name
{
    get;
    private set;    // means value could be set internally, and accessed through out
}

祝你在C#中好运!

答案 6 :(得分:4)

无论您在C#中选择哪种方式,最终结果都是相同的。您将获得具有单独的getter和setter方法的backinng变量。通过使用属性,您遵循最佳实践,因此这是您想要获得的详细信息。

就个人而言,我会选择自动属性,即最后一个版本:public string Name { get; set; },因为它们占用的空间最少。如果您需要添加类似验证的内容,您可以在将来扩展它们。

答案 7 :(得分:4)

只要有可能,我更喜欢公开string Name { get; set; },因为它简洁易读。但是,有时可能需要这个

private string name;

public string Name {
   get { return name; }
   set { name = value; }
}

答案 8 :(得分:4)

在C#中,首选方法是通过属性而不是getX()setX()方法。另外,请注意,C#不要求属性同时具有get和set - 您可以使用get-only属性和set-only属性。

public boolean MyProperty
{
    get { return something; }
}

public boolean MyProperty
{
    set { this.something = value; }
}

答案 9 :(得分:3)

如上所述,所有这些方法都会产生相同的结果。最重要的是你选择一个约定并坚持下去。我更喜欢使用最后两个属性示例。

答案 10 :(得分:2)

与此处的大多数答案一样,使用自动属性。直观,更少的代码行,更干净。如果您要序列化课程,请使用[Serializable]属性标记课程[DataConract] /。如果您使用[DataContract]使用

标记该成员
[DataMember(Name="aMoreFriendlyName")]
public string Name { get; set; }

私人或公共制定者取决于您的偏好。

另请注意,自动属性需要getter和setter(公共或私有)。

/*this is invalid*/
public string Name 
{ 
    get; 
   /* setter omitted to prove the point*/
}

或者,如果您只想获取/设置,请自己创建一个支持字段

答案 11 :(得分:0)

  

我应该使用哪一个?每种方法有哪些警告或细微之处?

使用属性时,有一个需要注意的警告:使用属性,您无法对getter或setter进行任何参数化。

例如,假设您要检索列表项,并且希望同时应用过滤器。使用get方法,您可以编写如下内容:

obj.getItems(filter);

相反,使用属性,您必须先返回所有项目

obj.items

,然后在下一步中应用过滤器,否则您必须添加专用属性以显示通过不同条件过滤的项目,这很快会使您的API膨胀:

obj.itemsFilteredByX
obj.itemsFilteredByY

有时候,当您开始使用某个属性(例如obj.items,然后后来发现需要进行getter或setter参数化,否则将使class-API用户更加轻松。现在,您需要重写API并修改代码中访问该属性的所有这些位置,或者找到替代解决方案。相比之下,使用get方法,例如obj.getItems(),您可以简单地扩展方法的签名以接受可选的“配置”对象,例如obj.getItems(options),而不必重写所有调用您的方法的地方。

话虽这么说,C#中的(自动实现的)属性仍然是非常有用的快捷方式(由于此处提到的各种原因),因为在大多数情况下可能不需要参数化,但这值得一提。