C# 自动属性 ​​- 为什么我必须写“get” 设置“”?

发布于 2024-07-09 11:37:32 字数 63 浏览 9 评论 0原文

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

若无相欠,怎会相见 2024-07-16 11:37:32

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

public int Foo { get; private set; }

或只写属性:

public int Foo { private get; set; }

Because you might want a read-only property:

public int Foo { get; private set; }

Or Write-only property:

public int Foo { private get; set; }
在巴黎塔顶看东京樱花 2024-07-16 11:37:32

属性或索引器可能无法作为 out 或 ref 参数传递

错误:如果您未指定 {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
    }
}

您不应该在类上创建公共字段/变量,您永远不知道什么时候需要将其更改为具有 get & 属性。 设置访问器,然后您不知道要破坏哪些代码,特别是如果您有针对您的 API 进行编程的客户端。

此外,您还可以为 get 和 get 方法使用不同的访问修饰符。 设置,例如 {get; private set;} 使 get 为公开,而 set 为声明类私有。

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

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.

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.

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

深陷 2024-07-16 11:37:32

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

编写如下所示的属性是 .net 3.0 快捷方式调用“自动实现的属性”。

public int MyProperty { get; set; }

这可以节省您一些打字时间。 声明属性的长方法如下:

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

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

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

从 IL 反汇编的 C# 代码

还连接了 setter 和 getter 的方法。

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

来自 IL 的反汇编 C# 代码

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

 public int MyProperty { get; private set; }

所有编译器都会将“set”标记为私有。 setter 和 getter 方法说的是相同的。

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

从 IL 反汇编 C# 代码

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

如果您查看声明只读属性的冗长方式:

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

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

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

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

从 IL 反汇编 C# 代码

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”.

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.

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

disassembled C# code from IL

Also wires up a method for the setter and 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

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

 public int MyProperty { get; private set; }

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

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

disassembled C# code from IL

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.

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

零時差 2024-07-16 11:37:32

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

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

public int MyProperty { get; private set; }

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; }
紙鸢 2024-07-16 11:37:32

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

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

梦中的蝴蝶 2024-07-16 11:37:32

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

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

開玄 2024-07-16 11:37:32

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

public int Foo;
public int Bar { }

那是可行的。 也就是说,这是编译器可以理解的语法。

但随后你就会遇到这样的情况:空块具有语义意义。 这看起来很不稳定。

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.

如此安好 2024-07-16 11:37:32

既然没有人提到它...您可以将自动属性虚拟并覆盖它:

public virtual int Property { get; set; }

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

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

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:

public override int Property { get { return int.MinValue; } }
半岛未凉 2024-07-16 11:37:32

另外,因为从 C# 6.0 开始(在 Visual Studio 2015 中,在终极预览版中提供此答案时),您可以实现真正的只读属性:

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

...而不是当前使用公共 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."; }

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

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

有关 C# 6.0 的其他精彩新闻可在此处。

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:

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:

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文