为什么我可以在接口中声明自动实现的属性
它们不是自动实现的,只是属性declaration的语法与自动实现的属性definition的语法相同。
这个:
interface IFoo
{
String Bar { get; set; }
}
意思是:“IFoo 有一个 public[1]String 属性名为 Bar,它有一个 getter 和一个 setter。”
这个:
class Foo
{
String Bar { get; set; }
}
意思是:“Foo 有一个 private[2]String 属性,名为 Bar,它有一个 getter 和一个 setter,以及 getter 和 setter都是由编译器自动生成的,并且对隐藏的实例字段进行操作。
请注意,接口中使用的语法与class 或struct 中实现使用的语法无关。所以给定与上面相同的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# 意义上),因为接口实现的子类不能任意@ 987654342@任意接口成员[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] 子类可以重新实现一个接口,该接口将具有覆盖对该接口成员的任何虚拟调用的效果,但仅如果该成员是通过接口引用而不是通过对类的超类型。