C# 接口 interface

在人类世界中,两个或更多人之间的契约约束他们按照契约行事。 同样,接口包括相关功能的声明。 实现接口的实体必须提供声明功能的实现。

在 C# 中,可以使用 interface 关键字定义接口。 接口可以包含方法、属性、索引器和事件的声明。 但是,它不能包含字段、自动实现的属性。

以下接口声明了文件操作的一些基本功能。

    interface IFile
    {
        void ReadFile();
        void WriteFile(string text);
    }

您不能将访问修饰符应用于接口成员。 默认情况下,所有成员都是公开的。 如果在接口中使用访问修饰符,则 C# 编译器将给出编译时错误"IFile.WriteFile(string)”必须声明主体,因为它未标记为 abstract、extern 或 partial"。(因为它会认为我们尝试做默认实现)

实现接口

一个类或一个结构可以使用冒号 (:) 实现一个或多个接口。

语法:<类或结构名称>:<接口名称>

例如,以下类隐式实现了 IFile 接口。

interface IFile
{
    string ReadFile();
    void WriteFile(string text);
    string Name { get; }
}

public class MyFile : IFile
{
    public string Name
    {
        get { return "test"; }
    }

    public string ReadFile()
    {
        return "hello world";
    }

    public void WriteFile(string text)
    {
        Console.WriteLine("写一个文件,这个是假的");
    }
}

在上面的例子中,FileInfo 类实现了 IFile 接口。 它用公共访问修饰符定义了 IFile 接口的所有成员。 FileInfo 类还可以包含接口成员以外的成员。 注意 接口成员必须使用 public 修饰符实现; 否则,编译器会给出编译时错误。

您可以创建类的对象并将其分配给接口类型的变量,如下所示。

class Program
{
    static void Main(string[] args)
    {
        IFile file1 = new MyFile();
        var file2 = new MyFile();

        file1.ReadFile();
        file1.WriteFile("content");

        file2.ReadFile();
        file2.WriteFile("content");
    }
}

上面我们看到 MyFile和 IFile都是可以调用ReadFile和WriteFile的。但是显式实现接口的时候会不一样。

显式实现

可以使用 <InterfaceName>.<MemberName> 显式实现接口。 当类实现多个接口时,显式实现很有用; 因此,它更具可读性并消除了混乱。 如果接口恰好具有相同的方法名称,这也很有用。

interface IFile
{
    string ReadFile();
    void WriteFile(string text);
}

class MyFile : IFile
{
    string IFile.ReadFile()
    {
        Console.WriteLine("Reading File");
        return "abc";
    }

    void IFile.WriteFile(string text)
    {
        Console.WriteLine("Writing to file");
    }
}

显式实现接口时,只能通过接口类型的实例访问接口成员。

interface IFile
{
    string ReadFile();
    void WriteFile(string text);
}

public class MyFile : IFile
{
    string IFile.ReadFile()
    {
        Console.WriteLine("Reading File");
        return "abc";
    }

    void IFile.WriteFile(string text)
    {
        Console.WriteLine("Writing to file");
    }

    public void Search(string text)
    {
        Console.WriteLine("Searching in file");
    }
}

class Program
{
    static void Main(string[] args)
    {
        IFile file1 = new MyFile();
        var file2 = new MyFile();

        file1.ReadFile();
        file1.WriteFile("content");
        //file1.Search("text to be searched")//编译错误,打点也是没有提示的

        file2.Search("text to be searched");
        //file2.ReadFile(); //编译错误
        //file2.WriteFile("content"); //编译错误
    }
}

在上面的例子中,file1 对象只能访问 IFile 的成员,file2 只能访问 MyFile 类的成员。 这是显式实现的限制。

实现多个接口

C# 中类是没有办法多继承的,但是可以实现多个接口如下。

interface IFile
{
    string ReadFile();
    void WriteFile(string text);
}

interface IBinaryFile
{
    void OpenBinaryFile();
    void ReadFile();
}

public class MyFile : IFile, IBinaryFile
{
    string IFile.ReadFile()
    {
        Console.WriteLine("Reading File");
        return "abc";
    }

    void IFile.WriteFile(string text)
    {
        Console.WriteLine("Writing to file");
    }

    public void Search(string text)
    {
        Console.WriteLine("Searching in file");
    }

    void IBinaryFile.OpenBinaryFile()
    {
        Console.WriteLine("Opening Binary File");
    }

    void IBinaryFile.ReadFile()
    {
        Console.WriteLine("Reading Binary File");
    }
}
class Program
{
    static void Main(string[] args)
    {
        IFile file1 = new MyFile();
        IBinaryFile file2 = new MyFile();
        MyFile file3 = new MyFile();

        file1.ReadFile(); //Reading File
        //file1.OpenBinaryFile(); //compile-time error 
        //file1.SearchFile("text to be searched"); //compile-time error 

        file2.OpenBinaryFile(); // Opening Binary File
        file2.ReadFile(); // Reading Binary File
        //file2.SearchFile("text to be searched"); //compile-time error 

        file3.Search("text to be searched"); // Searching in file
        //file3.ReadFile(); //compile-time error 
        //file3.OpenBinaryFile(); //compile-time error 
    }
}

上面,MyFile 显式地实现了两个接口 IFile 和 IBinaryFile。 建议在实现多个接口时显式实现接口,避免混淆,提高可读性。

多个类继承于同一个接口

很多时候我们会跟据条件来决定要使用哪一个类来做事情,下面代码就展示了这个简单的情况。

interface IFile
{
    void Hello();
}

public class MyFile : IFile
{
    public void Hello()
    {
        Console.WriteLine("MyFile");
    }
}

public class YourFile : IFile
{
    public void Hello()
    {
        Console.WriteLine("YourFile");
    }
}

class Program
{
    static void Main(string[] args)
    {
        IFile file1 = GetFile();

        file1.Hello();

    }

/// <summary>
/// 跟据条件返回具体的实现类
/// </summary>
/// <returns></returns>
private static IFile GetFile()
{
    IFile file1 = null;
    if (DateTime.Now.Ticks % 2 == 1) //模拟条件
    {
        file1 = new MyFile();
    }
    else
    {
        file1 = new YourFile();
    }
    return file1;
}
}

接口默认实现

从 C# 8.0 开始,接口成员可以声明主体。 这称为“默认实现”。 具有主体的成员允许接口为不提供重写实现的类和结构提供“默认”实现。 此外,从 C# 8.0 开始,接口可以包括:

  • 常量
  • 运算符
  • 静态构造函数。
  • 嵌套类型
  • 静态字段、方法、属性、索引和事件
  • 使用显式接口实现语法的成员声明。
  • 显式访问修饰符(默认访问权限为 public)。 (这个搞得象类一样了)
interface IFile
{
    public void Hello()
    {
        Console.WriteLine("hello");
    }
}

public class MyFile : IFile
{
    public void Hello2()
    {
        ((IFile)this).Hello();
    }
}

class Program
{
    static void Main(string[] args)
    {
        IFile file1 = new MyFile();
        var file2 = new MyFile();

        file1.Hello();
        // file2.Hello();//编译错误;
        file2.Hello2();
    }
}
下一篇:C# 操作符
最近更新的
...