简体   繁体   English

为什么我需要通过公共财产公开的私人领域?

[英]Why do I need a private field that is exposed via public property?

I'm comming from Java world mainly. 我主要来自Java世界。 So, C# properties do look nice. 所以,C#属性看起来不错。

I know that with C# 3.0 or above I can use Automatic Properties. 我知道使用C#3.0或更高版本我可以使用自动属性。 I like it even more :). 我更喜欢它:)。

My question is about a (maybe older) code where I can see this: 我的问题是一个(可能更旧的)代码,我可以看到这个:

   private int age;

   public int Age {

     get { return age; }
     set { age = value; }     
   }

Why do I need the private field age? 为什么我需要私人领域时代? What I'm I really hiding here? 我真的藏在这里的是什么?

EDIT: 编辑:

I completely understand the need for the getter and setter. 我完全理解对getter和setter的需求。 I mentioned that I'm comming from Java world and doing this all the time. 我提到我是从Java世界来的,并且一直这样做。

I do understand that Automatic Properties in C# 3.0 or above are syntatic sugar. 我知道C#3.0或以上的自动属性是合成糖。 But maybe my question has a simpler answer. 但也许我的问题有一个更简单的答案。 Does it means that (bellow C# 3.0) the property doesn't hold any value. 这是否意味着(低于C#3.0)该财产没有任何价值。 So it must get the value from some other field? 那么它必须从其他领域获得价值吗?

Older versions of C# didn't have automatic properties, so you had to declare your variables that the properties acted upon like in your example. 较旧版本的C#没有自动属性,因此您必须声明属性所执行的变量,如示例中所示。 These days, the same code could be expressed as: 这些天,相同的代码可以表示为:

public int Age { get; set; }

I think that answers your question. 我认为这回答了你的问题。 However, if you are asking "why not just have public int Age; and let programmers set the value on the field directly?", then: 但是,如果你问“为什么不公开int Age;并且让程序员直接在字段上设置值?”,那么:

First thing to keep in mind is that property accessors are compiled into methods. 首先要记住的是,属性访问器被编译成方法。 This means that it has a different ABI from just reading/writing to a class member variable, even though it may syntactically look the same as if you had: 这意味着它只有读取/写入类成员变量的ABI不同,即使它在语法上看起来与您拥有的相同:

class Fu {
  public int Age;
}

So, what this means is that if, at some point down the road, you need to add some notification that the Age field has changed - if you are using properties, you can easily add this notification logic to the property setter without breaking ABI. 因此,这意味着,如果在某个时候,您需要添加一些Age字段已更改的通知 - 如果您正在使用属性,则可以轻松地将此通知逻辑添加到属性设置器而不会破坏ABI。

public int Age {
  get { return age; }
  set { age = value; NotifySomeOtherCode (); }
}

If you start off with a public field, then later changing it to a property will change the ABI which is bad for any program(s) that may depend on your assembly. 如果您从公共字段开始,然后将其更改为属性将更改ABI,这对可能取决于您的程序集的任何程序都是不利的。 So it's better to start off with properties. 所以最好从属性开始。

Hopefully I'm making sense... 希望我有意义......

The automatic properties were not supported in older versions of the C# compiler. 旧版本的C#编译器不支持自动属性。

The above code is more or less equivalent to this (assuming that the field is never actually used directly): 上面的代码或多或少等同于此(假设该字段实际上从未直接使用过):

public int Age {
  get;
  set;
}

In this case you don't require it. 在这种情况下,您不需要它。 If you ever need to do anything else in the setter or getter, though, the automatic property won't work -- you'll need the private field to manipulate. 但是,如果您需要在setter或getter中执行任何其他操作,则自动属性将不起作用 - 您将需要私有字段进行操作。

Automatic properties in C#, when compiled, end up functionally exactly the same as the above code. C#中的自动属性在编译时,在功能上与上面的代码完全相同。 The compiler generates a backing field for you. 编译器为您生成一个支持字段。

So you do need something backing a property - a field or some code - it's just that it's taken care of for you with the shortcut of auto-properties. 所以你确实需要一些支持属性的东西 - 一个字段或一些代码 - 它只是用自动属性的快捷方式为你照顾。

The bog-standard answer would be "encapsulating the implementation detail of how and where the age is stored". 沼泽标准的答案是“封装年龄存储方式和位置的实施细节”。

For retrieval purposes, a more realistic example might be that one day, you could potentially want to access the value in a way that means direct access isn't so good. 出于检索目的,一个更现实的例子可能是,有一天,您可能希望以一种意味着直接访问不太好的方式访问该值。 For example, if it's a value that you might be caching elsewhere, or if it's a calculated value. 例如,如果它是您可能在其他地方缓存的值,或者它是计算值。

In terms of encapsulating the setting process, it means you can embed some model-level validation into the setter; 在封装设置过程方面,这意味着您可以将一些模型级验证嵌入到setter中; if someone tries to set a conceptually invalid value, you can throw an IllegalArgumentException and reject it. 如果有人试图设置概念上无效的值,您可以抛出IllegalArgumentException并拒绝它。

In these cases, the encapsulation means that all your existing code doesn't have to change because you had to wrap up the value in something. 在这些情况下,封装意味着您不必更改所有现有代码,因为您必须将值包装在某些内容中。

Properties are just a nice way to write a pair of a get and a set method. 属性只是编写一对getset方法的好方法。 In Java you would do this: 在Java中你会这样做:

private int age;

public int getAge() { return age; }
public void setAge(int value) { age = value; }

You need the private field to store the age somewhere -- getAge and setAge are just methods. 您需要私有字段来存储某个年龄 - getAge和setAge只是方法。

The same applies to C# to versions before 3.0: 这同样适用于3.0之前版本的C#:

private int age;

public int Age
{
   get { return age; }
   set { age = value; } 
}

This is a get and a set method, just nicely paired up so you can write x.Age = 21 instead of x.setAge(21) . 这是一个get和set方法,很好地配对,所以你可以写x.Age = 21而不是x.setAge(21)

With automatic properties, the C# compiler generates the private field for you (but it's still there!): 使用自动属性,C#编译器会为您生成私有字段(但它仍然存在!):

public int Age
{
   get;
   set;
}

The benefit of automatic properties is that you don't have to create the backing field manually yourself anymore. 自动属性的好处是您不必再自己手动创建支持字段。

The benefit of the manual version is, that you can add additional logic to the get and set methods, for instance, parameter validation: 手动版本的好处是,您可以为get和set方法添加额外的逻辑,例如,参数验证:

private int age;

public int Age
{
   get { return age; }
   set { if (value < 0) throw new ArgumentException(); age = value; } 
}

With the automatic properties, you don't need to do this. 随着自动属性,你并不需要这样做。 There's nothing wrong with it, but with automatic properties you'll still have your property signature , which is the important thing. 它没有任何问题,但有了自动属性,你仍然会拥有你的财产签名 ,这是重要的事情。 Before automatic properties, you had to have a backing field for your property. 在自动属性之前,您必须拥有属性的支持字段。 As long as you have an automatic property, you can later change it to the format with an explicit backing field, and the signature stays the same. 只要您具有自动属性,您可以稍后将其更改为具有显式支持字段的格式,并且签名保持不变。

But, there's nothing wrong with it. 但是,它没有任何问题。 Except that the convention is becoming more to call the private backing field "_age". 除了公约越来越多地称为私人支持领域“_age”。

(I assume you know why you want to have a property , whether automatic or not, instead of a public field . The reason is that the object has a different signature if you change form public field to public property, so it's safest to just start off with a property, even if there is no extra logic.) (我假设您知道为什么要拥有一个属性 ,无论是否为自动,而不是公共字段 。原因是如果您将表单公共字段更改为公共属性,则该对象具有不同的签名,因此最安全的是刚开始关闭财产,即使没有额外的逻辑。)

Maybe you want to change the behaviour of the setter or getter at a later point. 也许你想稍后改变setter或getter的行为。 eg log that the value was changed from outside. 例如记录值从外部改变。 this would not be possible with a public field without properties 对于没有属性的公共字段,这是不可能的

   private int age;

   public int Age {

     get { return age; }
     set { 
       age = value; 
       Log("value of age changed");
     }     
   }

With a public field age , you had to log this everywhere in the code where you change the value of age. 对于公共字段age ,您必须在更改年龄值的代码中随处记录。

In this case you aren't hiding anything but it will give you the freedom to add get/set logic to your private field later. 在这种情况下,您不会隐藏任何内容,但它可以让您自由地在以后向您的私有字段添加get / set逻辑。 So anyone who uses the property wont notice the difference in the future. 因此,使用该物业的任何人都不会注意到未来的差异。

In the simple case nothing. 在简单的情况下没有。 However you are making it easier to maintain the interface to the class should the implementation of either of those two methods require additional code. 但是,如果这两种方法中的任何一种的实现都需要额外的代码,那么就可以更容易地维护类的接口。

Take for instance if you need to add a changing event to the setter. 例如,如果您需要向setter添加更改事件。

   public int Age {

     get { return age; }
     set { 
          if ( age != value) {
              age = value; 
              OnAgeChanged();
          }
      }     
   }

You can do this with a property and not break client code. 您可以使用属性执行此操作,而不是破坏客户端代码。 A field does not have this advantage. 一个领域没有这个优势。

Getters and Setters are the public interface that other classes interact with. Getters和Setter是其他类与之交互的公共接口。 In complex systems you usually end up doing validation and other work inside the getter and setter. 在复杂系统中,您通常最终会在getter和setter中进行验证和其他工作。

The private field is for internal use. 私人领域供内部使用。 If you need to change the value from inside the class but bypass all the extra work you would change the private variable. 如果您需要更改类中的值但绕过所有额外的工作,您将更改私有变量。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何通过反射设置班级私人成员的公共领域的价值? - How do I set value of a class' private member's public field via Reflection? 为什么属性是公共的,而 setter 是私有的 - Why property is public and the setter is private 我应该使用带有公共获取方法的私有属性/字段还是直接使用公共属性进行正确封装? - Should I use a private property/field with a public getter method or directly use a public property for proper encapsulation? 为什么我可以更改私有静态只读字段而不是公共字段? - Why can I change a private static readonly field but not a public one? 我应该在声明该属性的类中使用公共属性的私有字段吗? - Should I use a private field of a public property inside a class where I declare that property? 使用Code Contracts,我是否需要通过`Ensures`验证字段/属性初始化? - With Code Contracts, do I need to verify field/property initialization via `Ensures`? 为什么我不能在静态类中访问公共属性字段 - Why can't I access public property field in static class 为什么在房屋中需要大括号 - Why do I need braces in a property C# public datatype variable(get; private set) 如果变量已经是 public,为什么我们需要 set 方法? - C# public datatype variable( get; private set) Why do we need set method if variable is already public? 为什么在实现INotifyPropertyChanged时需要私有字段 - Why do i need private fields when implementing INotifyPropertyChanged
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM