首页 文章

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

提问于
浏览
86

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

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

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#?

EDIT

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

那么一个非平凡的 property (也许是重要的处理和验证)呢?我是否仍然可以通过公共属性公开它,但是逻辑封装在 getset 中?为什么我应该/我应该使用专用的setter和getter方法(带有相关的处理和验证逻辑) .

12 回答

  • 17
    public string Name { get; set; }
    

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

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

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

  • 5

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

  • 12

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

    当使用属性时,有一个警告尚未提及:对于属性,您不能对getter或setter进行任何参数化 .

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

    obj.getItems(filter);
    

    相反,对于房产,您必须先退回所有物品

    obj.items
    

    然后在下一步中应用过滤器,或者您必须添加公开按不同条件过滤的项目的专用属性,这很快会使您的API膨胀:

    obj.itemsFilteredByX
    obj.itemsFilteredByY
    

    有时可能令人讨厌的是当你开始使用房产时,例如 obj.items 然后发现需要getter或setter-parametrization,或者让class-API用户更容易 . 您现在需要重写API并修改代码中访问此属性的所有位置或查找替代解决方案 . 相反,使用get方法,例如 obj.getItems() ,您可以简单地扩展方法的签名以接受可选的"configuration"对象,例如 obj.getItems(options) 无需重写所有调用方法的地方 .

    话虽如此,C#中的(自动实现的)属性仍然是非常有用的快捷方式(由于这里提到的各种原因),因为大多数时候可能不需要参数化 - 但是这个警告就是这样 .

  • 5

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

    public boolean MyProperty
    {
        get { return something; }
    }
    
    public boolean MyProperty
    {
        set { this.something = value; }
    }
    
  • 4

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

    // 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; }
    }
    

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

    使用.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#中好运

  • 2

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

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

    Pre-C# 6

    我'd use the last of these, for a trivial property. Note that I' d称这是一个公共 property ,因为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方法而不是使用属性是有意义的,特别是如果它们可能很昂贵并且您希望强调这一点 . 但是,你想要像这样的普通属性无论如何都要用普通的方法实现 - 这里的属性更加惯用 .

    C# 6

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

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

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

    public double Area => height * width;
    
  • 82

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

    public string Name { get; set; }
    

    想让它看起来只读吗?

    public string Name { get; private set; }
    

    甚至更好......

    private readonly string _name;
    
    ...
    
    public string Name { get { return _name; } }
    

    想要在分配 property 之前做一些 Value 检查吗?

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

    一般来说,GetXyz()和SetXyz()仅在某些情况下使用,你只需要在感觉正确时使用你的肠道 . 总的来说,我会说我期待最多获取/设置属性不包含大量逻辑,并且具有非常少的(如果有的话)意外的副作用 . 如果读取属性值需要调用服务或从用户那里获取输入以构建我正在请求的对象,那么我会将其包装到方法中,并将其称为 BuildXyz() ,而不是 GetXyz() .

  • 0

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

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

  • 4

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

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

  • 4

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

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

  • 4

    像这里的大多数答案一样,使用自动属性 . 直观,更少的代码行,更干净 . 如果要序列化类,请使用 [DataConract] 属性标记类 [Serializable] / . 如果您正在使用 [DataContract] 标记该成员

    [DataMember(Name="aMoreFriendlyName")]
    public string Name { get; set; }
    

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

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

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

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

相关问题