【问题标题】:Explanation of Interface usage (C# perspective)接口使用说明(C#视角)
【发布时间】:2013-02-26 19:26:27
【问题描述】:

我使用 C# 和 .NET 已经有一段时间了,尽管我之前一直在使用 OOP 语言(更准确地说是 Java),但在处理 .NET 应用程序时,我发现使用的接口比我在Java中见过。我根本没有太多经验,所以我并不是说接口在 .NET 中使用得更多,但现在我觉得有必要更深入地了解接口以及让人们经常使用它们的好处是什么.

我在互联网上有一些东西,这里有一些东西,对我来说最有意义的解释是 - How will I know when to create an interface?

我的问题来了。我根本不期望对接口进行一些神奇的解释,因为我已经阅读了足够多的内容,发现没有这样的东西。我希望通过经验和编码,更深层次的理解会自行产生,所以我决定尝试这个例子,指出使用链接中接受的答案中的接口的好处。我也复制粘贴到这里:

您有 4 种不同类型的 a、b、c、d。在你的代码中,你有类似的东西:

a.Process();
b.Process();
c.Process();
d.Process();

为什么不让他们实现IProcessable,然后做

List<IProcessable> list;

foreach(IProcessable p in list)
    p.Process();

当您添加 50 种类型的类都做同样的事情时,这将更好地扩展。

问题是我似乎没有这个。阅读后,我打开 Visual Studio 2010 并尝试重新创建这样的示例 - 我创建了一个项目并创建了四个类 - abcd。所有这些类都是相同的:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class a : ITest
    {
        public void Test()
        {
            System.Console.WriteLine("Hi from a");
        }
    }
}

只有 4 个不同的名称和方法 Test() 打印名称。界面如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    interface ITest
    {
        public void Test();
    }
}

根据我在Program.cs 中的理解,我有这个:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        List<ITest> list;
        static void Main(string[] args)
        {
            foreach (ITest p in list)
                p.Test();
        }
    }
}

嗯。看来我真的搞错了。我认为通过实现相同的接口,我可以自动获取所有类的列表并使用它们,例如在我上面的Main() 方法中。但是我收到以下错误:

非静态字段、方法或属性需要对象引用

好吧,谁能降低我的水平,并根据这个例子解释我如何通过使用界面来获得这样的好处。

【问题讨论】:

  • 接口不是这里的问题——它是Programlist 字段。这需要是一个静态字段才能从静态方法Main 中使用它。 (您可能还想在该列表中添加一些内容)
  • 这将是一个很好的阅读 - stackoverflow.com/q/14482483/218882

标签: c# oop interface


【解决方案1】:

这里的问题与接口无关,而是与Program 类有关。字段list 是实例成员,而方法Main 是静态的。正如例外所说,您不能从静态方法中引用非静态成员。

此外,list 从未实例化或初始化(至少不在您发布的 sn-p 中)。因此,即使 list 被声明为静态,您的代码也会生成 NullReferenceException

尝试将您的 Program 类更改为:

class Program
{
    static List<ITest> list;
    static void Main(string[] args)
    {
        list = new List<ITest>();
        // ...
        // initialize list 
        // ...

        foreach (ITest p in list)
            p.Test();
    }
}

【讨论】:

    【解决方案2】:

    您的代码在创建将实现接口的类方面看起来不错。问题似乎在于您的初始化。

    正如您声明的那样,List&lt;ITest&gt; list 不是静态字段。 Main函数是静态方法,所以只能访问其他静态字段。

    如果您想继续这个基本示例,请尝试将list 设置为静态字段,或设置为Main 中的变量,并对其进行实例化,在您的foreach 循环中使用之前填充一些对象.

    【讨论】:

      【解决方案3】:

      关于您的错误,看起来list 没有实例化,它是一个实例字段,可以从静态方法访问。


      接口不是为了继承,而是为了多态。

      界面不是用来保存代码的。如果您需要这样做,请使用抽象类。

      接口所做的只是向编译器保证您的类将以特定方式运行。它没有指定任何关于实现的内容。

      例如,ListLinkedList 的实现方式不同,但它们都符合 IEnumberable 接口,因此可以在 foreach 循环中进行迭代

      【讨论】:

        【解决方案4】:

        接口的用法是定义一个对象的占位符之类的东西,它肯定会有一些特定的行为,而实际上并不知道它。例如,您可以有 A 类和 B 类,它们都实现了 IMyInterface。如果您需要 IMyInterface 的实例,您可以同时使用它们并调用接口中指定但在 A 或 B 中实现的方法。此外,IoC 容器中的接口也有很好的基于约定的用法。

        【讨论】:

          猜你喜欢
          • 2015-03-17
          • 2018-02-01
          • 1970-01-01
          • 2011-01-28
          • 2015-03-16
          • 1970-01-01
          • 2012-06-25
          • 2018-01-01
          • 2013-07-11
          相关资源
          最近更新 更多