简体   繁体   English

封装C#newbie

[英]Encapsulation C# newbie

New to C#, and I understand that encapsulation is just a way of "protecting data". C#的新手,我知道封装只是一种“保护数据”的方式。 But I am still unclear. 但我还不清楚。 I thought that the point of get and set accessors were to add tests within those methods to check to see if parameters meet certain criteria, before allowing an external function to get and set anything, like this: 我认为,get和set访问都添加这些方法中的测试,以检查是否参数满足一定条件,允许外部函数来获取和设置任何东西,这样才:

private string myName;
public string MyName;// this is a property, speical to c#, which sets the backing field.

private string myName = "mary";// the backing field.

public string MyName // this is a property, which sets/gets the backing field.
{
    get
    {
        return myName;
    }
    set
    {
        if (value != "Silly Woman"){ 
           myName = value;
        }

    } 
}

But I've been seeing code in c# which just looks like this: 但是我一直在看c#中的代码看起来像这样:

public string MyName { get; set; }

Why would you just have a get and set with nothing in there, - isn't that the same as just declaring your private backing field public? 为什么你只是在那里得到一个没有任何东西的get-set, - 这不仅仅是公开你的私人支持领域吗? If you can just get and set it from outside, why wouldn't you just do it directly? 如果您可以从外部获取并设置它,为什么不直接进行?

Indeed, creating an auto-property as follows: 实际上,创建一个自动属性如下:

public string Name { get; set; }

is identical to building a property backed by a field: 与构建由字段支持的属性相同:

private string _name;
public string Name {
    get { return _name; }
    set { _name = value; }
}

The point of these properties is not to hide data. 这些属性的重点不是隐藏数据。 As you observed, they don't do this. 正如你所观察到的,他们不会这样做。 Instead, these properties can do other stuff instead of just working with a field: 相反,这些属性可以执行其他操作,而不仅仅是使用字段:

public string Name {
    get { return _name; }
    set { if (value == null) throw new Exception("GTFO!"); _name = value; }
}

Another thing is, you can make properties virtual : 另一件事是,你可以使属性虚拟

public virtual string Name { get; set; }

which, if overridden, can provide different results and behaviours in a derived class. 如果被覆盖,则可以在派生类中提供不同的结果和行为。

By using public string MyName { get; set; } 通过使用public string MyName { get; set; } public string MyName { get; set; } public string MyName { get; set; } , you leave an ability to change its logic later without the need to recompile/change other code that uses your property. public string MyName { get; set; } ,你离开以后更改它的逻辑,而无需重新编译/改变使用你的财产的其他代码的能力。

For example, if you are making a library and v1 uses a field and v2 uses a property, applications that work with v1 will not work with v2 without recompilation (and, potentially, code changes if they are written in some .NET language that has different syntax for accessing fields). 例如,如果您正在创建一个库并且v1使用一个字段而v2使用一个属性,那么使用v1的应用程序将无法在不重新编译的情况下使用v2(如果它们是用某种.NET语言编写的,则可能会更改代码访问字段的不同语法)。

Another important difference is in serialization scenarios -- a lot of them do not support fields. 另一个重要的区别在于序列化场景 - 其中很多都不支持字段。 Also any interface that requires a property can not be implemented without using one, but depending on interface it may not be required to do any additional checks/logic in it. 此外,任何需要属性的接口都不能在不使用属性的情况下实现,但根据接口,可能不需要在其中执行任何其他检查/逻辑。

Because it is easier to change the Code if you want to add the checks/tests later on. 如果您想稍后添加检查/测试,则更容易更改代码。 Especially if you have many inheritance and many classes in your code it is very hard to change the implementation from a public variable to a public Property. 特别是如果您的代码中有许多继承和许多类,则很难将实现从公共变量更改为公共属性。

Moreover you can add to the get and set within the property different attributes, eg if you are using reflection. 此外,您可以在属性中添加get和set不同的属性,例如,如果您正在使用反射。 The get and set of the property are internally different methods. 属性的get和set是内部不同的方法。 If you have just a public variable /field it is not possible to added different properties to the different access ways. 如果您只有一个公共变量/字段,则无法为不同的访问方式添加不同的属性。

Yeah, but you can easily change it to: 是的,但您可以轻松地将其更改为:

public string MyName { get; private set; }

Plus, properties are used in other scenarios, like DataContract s and Serialization... so, this is a nice feature... (Mostly, syntactic sugar. I think) EDIT: I take that back.. you can apply virtual to it, so it's not the same 另外,属性在其他场景中使用,比如DataContract和Serialization ......所以,这是一个很好的功能...(大多数,语法糖。我认为)编辑:我把它拿回来...你可以应用虚拟它,所以它不一样

It makes it easier to add logic later. 它使以后更容易添加逻辑。 If you have a class that has a public field that you want to change to a property, you have to recompile everything that uses your class. 如果您的类具有要更改为属性的公共字段,则必须重新编译使用该类的所有内容。 That's a key point that I didn't understand initially. 这是我最初不理解的关键点。

If you have a class: 如果你有一个班级:

public class MyClass
{
    public string MyString;
}

You could access the value like this: 您可以像这样访问值:

var myClass = new MyClass();
string s = myClass.MyString;

Now change that to a property: 现在将其更改为属性:

public class MyClass
{
    public string MyString { get; set; }
}

How is it accessed? 怎么访问? The exact same way: 完全相同的方式:

var myClass = new MyClass();
string s = myClass.MyString;

So no big deal, right? 没什么大不了的,对吧? Well, actually.... 实际上....

Properties are actually compiled into getter and setter methods: 实际上,属性被编译为getter和setter方法:

get_MyString() and set_MyString(string value) get_MyString()set_MyString(string value)

So the two methods do produce different compiled code. 所以这两种方法确实产生了不同的编译代码。 Now if all your code that uses this class is in the same project, is not as big a deal, because it will all be compiled together. 现在,如果您使用此类的所有代码都在同一个项目中,那么这并不是一件大事,因为它将全部编译在一起。 But if you have an API library that you've distributed, it can be a much bigger deal to update. 但是,如果您有一个已经分发的API库,那么更新它可能会更大。

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM