簡體   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