例如,假设我想要一个ICar接口,并且所有实现都将包含字段Year。这是否意味着每个实现都必须单独声明Year?在接口中简单地定义它不是更好吗?


当前回答

从c# 8.0开始,接口可以为成员定义默认实现,包括属性。很少在接口中为属性定义默认实现,因为接口可能不定义实例数据字段。

https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/interface-properties

interface IEmployee
{
    string Name
    {
        get;
        set;
    }

    int Counter
    {
        get;
    }
}

public class Employee : IEmployee
{
    public static int numberOfEmployees;

    private string _name;
    public string Name  // read-write instance property
    {
        get => _name;
        set => _name = value;
    }

    private int _counter;
    public int Counter  // read-only instance property
    {
        get => _counter;
    }

    // constructor
    public Employee() => _counter = ++numberOfEmployees;
}

其他回答

将其声明为属性:

interface ICar {
   int Year { get; set; }
}

接口不包含任何实现。

定义带有属性的接口。 此外,您可以在任何类中实现该接口,并继续使用该类。 如果需要,可以在类中将此属性定义为virtual,以便修改其行为。

其他人已经给出了“为什么”,所以我只是补充说,你的界面可以定义一个控件;如果你把它包装在属性中:

public interface IView {
    Control Year { get; }
}


public Form : IView {
    public Control Year { get { return uxYear; } } //numeric text box or whatever
}

c#中的接口旨在定义类将遵循的契约——而不是特定的实现。

基于这种精神,c#接口确实允许定义属性——调用者必须为其提供一个实现:

interface ICar
{
    int Year { get; set; }
}

实现类可以使用auto-properties来简化实现,如果没有与属性相关的特殊逻辑的话:

class Automobile : ICar
{
    public int Year { get; set; } // automatically implemented
}

从c# 8.0开始,接口可以为成员定义默认实现,包括属性。很少在接口中为属性定义默认实现,因为接口可能不定义实例数据字段。

https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/interface-properties

interface IEmployee
{
    string Name
    {
        get;
        set;
    }

    int Counter
    {
        get;
    }
}

public class Employee : IEmployee
{
    public static int numberOfEmployees;

    private string _name;
    public string Name  // read-write instance property
    {
        get => _name;
        set => _name = value;
    }

    private int _counter;
    public int Counter  // read-only instance property
    {
        get => _counter;
    }

    // constructor
    public Employee() => _counter = ++numberOfEmployees;
}