属性和变量有什​​么区别


78

我对理解属性和变量感到困惑

public class ABC()
{
    public int A;
    public int B { get; set; }
}

A和B之间的确切区别是什么?


15
FYIA通常称为字段,而不是变量。
布赖恩·拉斯穆森




Answers:


71

正如许多人指出的那样,A是一个字段,B是一个属性

真正的问题是,您为什么要关心以及使用什么?

我指的是Jonathan Aneja博客文章

(在VB中,但它也适用于C#;)

那么,为什么要对字段使用属性,有五个原因:

1.字段不能在接口中使用

您不能通过接口强制对象的公共合同中存在字段。对于属性,虽然效果很好。

2.验证

尽管您的应用程序当前可能不需要任何验证逻辑来​​设置特定值,但是更改业务需求可能需要稍后插入此逻辑。那时,将字段更改为属性对于API使用者来说是一项重大更改。(例如,如果有人通过反射检查您的班级)。

3.二进制序列化

如果使用二进制序列化,则将字段更改为属性是一项重大更改。顺便说一句,这就是VB10的自动实现属性具有“可绑定”后备字段(即,您可以在代码中表示后备字段的名称)的原因之一–如果您将自动实现的属性更改为扩展的属性,您仍然可以通过保持背景字段名称相同来保持序列化兼容性(在C#中,您必须更改它,因为它会生成具有不可绑定名称的背景字段)。

4.许多.NET数据绑定基础结构绑定到属性,但不绑定到字段

我已经听过双方关于这是否是一件好事的争论,但现实是这就是现在的工作方式。(请注意:WPF绑定适用于属性)

5.暴露公共场所违反FxCop

由于上述许多原因:)

可能还有更多原因。

我还想指出Jeff Atwood博客文章,并引用其中的引言:

要带走的真正重要的事情是避免编写无关紧要的代码。围绕公共变量的属性包装器是毫无意义的代码的本质。


1
但是,自动实现的属性不能用作out参数:/ yay c#将无意义的代码强加给我们
Assimilater

对于第5项的更新的文档- CA1051:不要声明可见实例字段docs.microsoft.com/en-us/visualstudio/code-quality/...
蒂亚戈Crizanto

23

A是字段,B是属性。对于获取器和设置器,属性基本上是语法糖。您定义的类将被编译成如下形式:

public class ABC()
{
    public int A;

    private int backing_B;

    public void set_B(int value)
    {
        backing_B = value;
    }

    public int get_B()
    {
        return backing_B;
    }
}

请注意,这种转换对所有C#属性都是正确的-对ABC.B的访问将转换为方法调用。属性基本上提供了“变量”的错觉,而实际上只是巧妙地伪装了一对方法。

这很重要,因为它允许您声明自己的get和set方法主体,该主体可以验证值或执行其他有趣的操作:

private int b;

public int B {
    get { return b; }
    set {
        if (value < 0) throw new ArgumentOutOfRangeException("value");
        b = value;
    }
}

请注意,大多数属性将使用字段来存储其值。除了字段之外,属性很少单独存在。


4

属性有点像一个简短的getter和setter。您可以添加逻辑来setget财产或使他们私人,这意味着他们没有从出方,其中一个变量始终是可访问的(如果它是公共的)访问。


4

在C#中,任何具有getter和setter的“变量”都称为属性。变量没有getter和setter,所以这就是教科书所说的。

我的编程讲师使我们对用Java创建的几乎每个变量都有getter和setter方法。即使是在全局类范围内声明的索引变量,他也使我们使用了getter和setter方法。我认为这可能是过分的,但这确实使我成为吸气者和二传手。

关于getter和setter的真实之处在于,它们不仅仅是设置内部变量,而且更有可能做更多的事情。大多数设置器将执行某种类型的数据验证,以确保可以将数据设置为变量。吸气剂可能还会检查返回数据是否符合某些条件。

如果您的财产是私有的,而您的设置者和获取者是公开的,那么从技术上讲,任何人都可以访问您的变量并对其进行更改,就好像他们可以公开访问实际变量一样。因此,实际上,您应该检查数据以确保其有效或进行其他一些数据检查。

private int myVariable;
public int myVariable 
{
    get 
    { 
       return myVariable; 
    }
    set 
    {
        if (value < 0) 
        { 
           throw new Exception("This is your exception some where else in code");
        }
        myVariable = value; //remember value is something that is
                            //declared automatically
    }
}

public string FirstName { get; set; }

上面是写以下内容的简写方式

private string firstName;

public string FirstName
{
    get
    {
       //...code here
    }

    set
    {
       //...code here
    }
}

3

变量就是变量。

属性是一种公开该变量的特殊方法。而且,由于它是一种方法,因此您可以在其中做其他事情,而不仅仅是暴露变量。

从MSDN:

Property语句引入属性的声明。属性可以具有“获取”过程(只读),“设置”过程(只读)或同时具有两者(读写)。使用自动实现的属性时,可以省略Get and Set过程。有关更多信息,请参见自动实现的属性(Visual Basic)。

您只能在课程级别使用Property。这意味着属性的声明上下文必须是类,结构,模块或接口,并且不能是源文件,名称空间,过程或块。有关更多信息,请参见声明上下文和默认访问级别。

默认情况下,属性使用公共访问权限。您可以使用Property语句上的访问修饰符来调整属性的访问级别,还可以选择将其属性过程之一调整为限制性更高的访问级别。


0

在您的示例A中,该类是一个公共字段,ABC并且B是该类的公共财产ABC。具体来说,B是一个自动实现的属性。这意味着编译器“在幕后”为您完成了一些工作,并将您的代码有效地转换为:

public class ABC()
{
   private int b;

   public int A;
   public int B
   {
       get
       {
          return b;
       }
       set
       {
          b = value;
       }
   }
}

0

变量的定义基本上是根据分配给这些变量的修饰符从一个类或进入同一类的值。

当我们定义一个属性时,会为单个属性创建两个方法,因此会产生额外的开销,这是属性的缺点。

属性的优点是将值获取或设置为类的私有变量。


0

有一篇很好的文章(下面的链接)关于使用Microsoft本身的字段/变量与属性。尽管本文主要讨论了FxCop违反规则,但它明确定义了两者之间的区别以及确切的使用准则。

文章摘录:

字段的主要用途应作为实现细节。字段应该是私有的或内部的,并且应该通过使用属性来公开。访问属性就像访问字段一样容易,并且属性的访问器中的代码可以随着类型功能的扩展而变化,而不会引入重大更改。

参考:https : //docs.microsoft.com/zh-cn/previous-versions/dotnet/netframework-3.0/ms182141(v=vs.80)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.