C# 自动属性 ​​- 为什么我必须编写“get; set;”?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/340528/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 23:50:10  来源:igfitidea点击:

C# Automatic Properties - Why Do I Have To Write "get; set;"?

c#c#-3.0automatic-properties

提问by Ben Aston

If both get and set are compulsory in C# automatic properties, why do I have to bother specifying "get; set;" at all?

如果在 C# 自动属性中 get 和 set 都是强制性的,为什么我必须费心指定“get; set;” 根本?

采纳答案by Binary Worrier

ERROR: A property or indexer may not be passed as an out or ref parameter

错误:属性或索引器不能作为 out 或 ref 参数传递

If you didn't specify {get; set;}then the compiler wouldn't know if it's a field or a property. This is important becasue while they "look" identical the compiler treats them differently. e.g. Calling "InitAnInt" on the property raises an error.

如果您没有指定,{get; set;}那么编译器将不知道它是字段还是属性。这很重要,因为当它们“看起来”相同时,编译器会以不同的方式对待它们。例如,在属性上调用“InitAnInt”会引发错误。

class Test
{
    public int n;
    public int i { get; set; }
    public void InitAnInt(out int p)
    {
        p = 100;
    }
    public Test()
    {
        InitAnInt(out n); // This is OK
        InitAnInt(out i); // ERROR: A property or indexer may not be passed 
                          // as an out or ref parameter
    }
}

You shouldn't create public fields/Variables on classes, you never know when you'll want to change it to have get & set accessors, and then you don't know what code you're going to break, especially if you have clients that program against your API.

你不应该在类上创建公共字段/变量,你永远不知道什么时候你会想要改变它以获得和设置访问器,然后你不知道你要破坏什么代码,特别是如果你有针对您的 API 进行编程的客户端。

Also you can have different access modifiers for the get & set, e.g. {get; privateset;} makes the get public and the the set private to the declaring class.

您还可以为 get & set 设置不同的访问修饰符,例如 {get; privateset;} 使 get public 和 set 对声明类私有。

回答by Brian Genisio

Because you might want a read-only property:

因为您可能需要只读属性:

public int Foo { get; private set; }

Or Write-only property:

或只写属性:

public int Foo { private get; set; }

回答by Kris

The compiler needs to know if you want it to generate a getter and/or a setter, or perhaps are declaring a field.

编译器需要知道您是否希望它生成一个 getter 和/或一个 setter,或者是否要声明一个字段。

回答by Cristian Libardo

Because you need some way to distinguish it from plain fields.

因为您需要某种方式将其与普通字段区分开来。

It's also useful to have different access modifiers, e.g.

拥有不同的访问修饰符也很有用,例如

public int MyProperty { get; private set; }

回答by Rune Grimstad

If the property didn't have accessors, how would the compiler separate it from a field? And what would separate it from a field?

如果属性没有访问器,编译器将如何将它与字段分开?什么将它与一个领域分开?

回答by Ron Todosichuk

Just thought I would share my findings on this topic.

只是想我会分享我在这个主题上的发现。

Coding a property like the following, is a .net 3.0 shortcut call “auto-implemented property”.

像下面这样编写一个属性,是一个 .net 3.0 快捷方式调用“自动实现的属性”。

public int MyProperty { get; set; }

This saves you some typing. The long way to declare a property is like this:

这可以为您节省一些打字时间。声明一个属性的长路是这样的:

private int myProperty;
public int MyProperty 
{
  get { return myProperty; }
  set { myProperty = value; } 
}

When you use the “auto-implemented property” the compiler generates the code to wire up the get and set to some “k_BackingField”. Below is the disassembled code using Reflector.

当您使用“自动实现的属性”时,编译器会生成代码来连接 get 和 set 到某个“k_BackingField”。下面是使用 Reflector 反汇编的代码。

public int MyProperty
{
    [CompilerGenerated]
    get
    {
        return this.<MyProperty>k__BackingField;
    }
    [CompilerGenerated]
    set
    {
        this.<MyProperty>k__BackingField = value;
    }
}

disassembled C# code from IL

从 IL 反汇编的 C# 代码

Also wires up a method for the setter and getter.

还为 setter 和 getter 连接了一个方法。

[CompilerGenerated]
public void set_MyProperty(int value)
{
    this.<MyProperty>k__BackingField = value;
}
[CompilerGenerated]
public int get_MyProperty()
{
    return this.<MyProperty>k__BackingField;
}

disassembled C# code from IL

从 IL 反汇编的 C# 代码

When you declare a read only auto-implemented property, by setting the setter to private:

当您声明只读的自动实现属性时,通过将 setter 设置为私有:

 public int MyProperty { get; private set; }

All the compiler does flag the "set" as private. The setter and getter method say the same.

所有编译器都将“ set”标记为私有。setter 和 getter 方法也是如此。

public int MyProperty
{
    [CompilerGenerated]
    get
    {
        return this.<MyProperty>k__BackingField;
    }
    private [CompilerGenerated]
    set
    {
        this.<MyProperty>k__BackingField = value;
    }
}

disassembled C# code from IL

从 IL 反汇编的 C# 代码

So I am not sure why the framework require both the get; and set; on an auto-implemented property. They could have just not written the set and setter method if it was not supplied. But there may be some compiler level issue that makes this difficult, I don't know.

所以我不确定为什么框架需要 get; 并设置;在自动实现的属性上。如果没有提供 set 和 setter 方法,他们可能只是不编写。但是可能存在一些编译器级别的问题使这变得困难,我不知道。

If you look at the long way of declaring a read only property:

如果您查看声明只读属性的漫长方法:

public int myProperty = 0;
public int MyProperty
{
    get { return myProperty; }
}  

And then look at the disassembled code. The setter is not there at all.

然后看看反汇编的代码。二传手根本不在那里。

public int Test2
{
    get
    {
        return this._test;
    }
}

public int get_Test2()
{
    return this._test;
}

disassembled C# code from IL

从 IL 反汇编的 C# 代码

回答by Robert Rossney

Well, obviously you need a way of disambiguating between fields and properties. But are required keywords really necessary? For instance, it's clear that these two declarations are different:

好吧,显然您需要一种消除字段和属性之间歧义的方法。但是必需的关键字真的有必要吗?例如,很明显这两个声明是不同的:

public int Foo;
public int Bar { }

That could work. That is, it's a syntax that a compiler could conceivably make sense of.

那可以工作。也就是说,这是一种编译器可以理解的语法。

But then you get to a situation where an empty block has semantic meaning. That seems precarious.

但是随后您会遇到一种情况,即空块具有语义含义。这似乎很不稳定。

回答by Zaid Masud

Since no one mentioned it... you could make the auto-property virtual and override it:

由于没有人提到它……您可以将自动属性设为虚拟并覆盖它:

public virtual int Property { get; set; }

If there was no get/set, how would it be overridden? Note that you are allowed to override the getter and not the setter:

如果没有 get/set,它将如何被覆盖?请注意,您可以 覆盖 getter 而不是 setter

public override int Property { get { return int.MinValue; } }

回答by Robert Kope?

Also, because ever since C# 6.0 (in Visual Studio 2015, at the time of this answer available in version Ultimate Preview) you may implement a true read-only property:

此外,因为自 C# 6.0(在 Visual Studio 2015 中,在此答案在 Ultimate Preview 版本中可用)以来,您可以实现真正的只读属性:

public string Name { get; }
public string Name { get; } = "This won't change even internally";

... as opposed to currently imperfect workaround with public getter/private setter pair:

...与目前使用公共 getter/private setter 对的不完美解决方法相反:

public string Name { get; private set; }

public Constructor() { Name="As initialised"; }
public void Method() { Name="This might be changed internally. By mistake. Or not."; }

Example of the above below (compiled and executable online here).

上面的示例(在此处在线编译和可执行)。

using System;

public class Propertier {
    public string ReadOnlyPlease { get; private set; }

    public Propertier()  { ReadOnlyPlease="As initialised"; }
    public void Method() { ReadOnlyPlease="This might be changed internally"; }
    public override string ToString() { return String.Format("[{0}]",ReadOnlyPlease); }
}

public class Program {
    static void Main() {
        Propertier p=new Propertier();
        Console.WriteLine(p);

//      p.ReadOnlyPlease="Changing externally!";
//      Console.WriteLine(p);

        // error CS0272: The property or indexer `Propertier.ReadOnlyPlease' cannot be used in this context because the set accessor is inaccessible
        // That's good and intended.

        // But...
        p.Method();
        Console.WriteLine(p);
    }
}

Other tasty news about C# 6.0 available as official preview video here.

其他有关 C# 6.0 的好消息可在此处作为官方预览视频获得。