繁体   English   中英

自动实现的属性如何在 C# 接口中工作?

[英]How do Auto-Implemented properties work in C# interfaces?

如果我在 C# 类中声明自动实现的属性,则public string Property { get; set; } public string Property { get; set; } public string Property { get; set; }变成:

private string _property;

public string get_Property() {
    return _property;
}

public void set_Property(string value) {
    _property = value;
}

其中包括一个私有字段string _property

如果我创建一个接口,我可以像这样使用自动实现的属性:

string Property { get; set; }

为什么我可以在 Interface 中声明 Auto-Implemented 属性,但我不能使用更长、更详细的语法来声明私有字段? 我知道这样的定义:

接口仅包含方法、属性、事件或索引器的签名

接口中的私有字段与类中的生成方式不同吗? 它是完全生成的吗?

为什么我可以在 Interface 中声明 Auto-Implemented 属性

它们不是自动实现的,只是属性声明的语法与自动实现的属性定义的语法相同。

这个:

interface IFoo
{
    String Bar { get; set; }
}

意思是:“ IFoo有一个名为Bar公共[1] String属性,它有一个 getter 和一个 setter。”

这个:

class Foo
{
    String Bar { get; set; }
}

意思是:" Foo有一个名为Bar私有[2] String属性,它有一个 getter 和一个 setter,getter 和 setter 都是编译器自动生成的,并在隐藏的实例字段上操作。


请注意,接口中使用的语法与classstruct中的实现使用的语法无关。 所以给定与上面相同的IFoo ......

interface IFoo
{
    String Bar { get; set; }
}

...我们可以有:

// Using auto-implemented property:
class Foo2 : IFoo
{
    public String Bar { get; set; }
}
// Using explicit backing field:
class Foo3 : IFoo
{
    private String bar;

    public String Bar
    {
        get { return this.bar; }
        set { this.bar = value; }
    }
}
// Using expression-body syntax with a backing field:
class Foo4 : IFoo
{
    private String bar;

    public String Bar
    {
        get => this.bar;
        set => this.bar = value;
    }
}
// Using explicit interface implementation with a backing field:
class Foo5 : IFoo
{
    private String bar;

    String IFoo.Bar
    {
        get { return this.bar; }
        set { this.bar = value; }
    }
}

// You can also use explicit interface implementation with an auto-implemented property:
class Foo6 : IFoo
{
    String IFoo.Bar { get; set; }
}
// However, if it's a getter-only property you won't be able to set a property value in the constructor - but you can initialize it inline:
interface IReadOnlyFoo
{
    String Bar { get; }
}

class Foo7 : IReadOnlyFoo
{
    String IReadOnlyFoo.Bar { get; } = "foo"; // ok
}

class Foo8 : IReadOnlyFoo
{
    public Foo8()
    {
        this.Bar = "foo"; // <-- Error. `Bar` is not a member of `this`.
        // You also can't cast `(IReadOnlyFoo)this` because `IReadOnlyFoo` does not contain a setter.
    }

    String IReadOnlyFoo.Bar { get; }
}

接口中的私有字段是否与类中生成的不同

接口没有字段,接口只有虚拟方法(或者更确切地说: interface可以被认为是单个 vtable)。 请注意,在内部:属性和事件基本上也是虚拟方法(还要注意,虽然在内部它们是虚拟调用,但实现的接口方法不会自动virtual (在 C# 意义上),因为接口实现的子类不能任意override任何接口成员[3]

也不要与 C# 8.0 中的“默认接口实现”混淆,后者更类似于扩展方法而不是将接口视为类,因为接口仍然不能有字段。

您还应该熟悉 C# 的表达式主体成员语法(尽管它不常用于属性设置器):

class Foo2
{
    String bar; // this is a private instance field

    String Bar // this is a private instance property
    {
        get => this.bar;
        set => this.bar = value;
    }
}

[1] 当然,不考虑显式接口实现。
[2] 如果类成员没有明确的访问修饰符,则默认情况下它们是私有的。
[3] 子类可以重新实现一个接口,该接口将具有覆盖对该接口成员的任何虚拟调用的效果,但前提是该成员是通过接口引用而不是通过对类的超类型的对象引用来访问的。

暂无
暂无

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

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