我现在使用 C# 和 .NET 一段时间了,尽管我以前一直在使用 OOP 语言(更准确地说是 Java),但在开发 .NET 应用程序时,我发现接口的使用比我多得多。在Java中见过。我根本没有太多经验,所以我并不是说接口在 .NET 中使用更多,但现在我觉得有必要更深入地了解接口以及人们经常使用它们的好处是什么.
我在互联网上有一些东西,这里有一些东西,对我来说最有意义的解释是 - 我如何知道何时创建界面?。
我的问题来了。我根本不期望对接口有一些神奇的解释,因为我已经阅读了足够多的内容,发现不存在这样的东西。我希望通过经验和编码,更深入的理解会自然而然地实现,因此我决定尝试使用链接中已接受答案中的接口指出的示例。我也将其复制粘贴到这里:
你有 a、b、c、d 4 种不同类型。在你的代码中你都有这样的东西:
a.Process();
b.Process();
c.Process();
d.Process();
为什么不让他们实施
IProcessable
,然后再做
List<IProcessable> list;
foreach(IProcessable p in list)
p.Process();
当您添加 50 种类型的类(例如,所有类都执行相同的操作)时,这会扩展得更好。
问题是我似乎还没有得到这个。读完后,我打开 Visual Studio 2010 并尝试重新创建这样的示例 - 我创建了一个项目并创建了四个类 -
a
、b
、c
、d
。所有这些课程都是相同的:
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()
方法。但是我收到以下错误:
非静态字段、方法或属性需要对象引用
好吧,有人可以向我降低级别并根据这个示例向我解释一下我如何通过使用接口来受益。
这里的问题与接口无关,而是与类
Program
有关。字段 list
是实例成员,而方法 Main
是静态的。正如例外情况所示,您不能从静态方法引用非静态成员。
此外,
list
从未被实例化或初始化(至少在您发布的代码片段中)。因此,即使 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();
}
}
您的代码在创建将实现接口的类方面看起来不错。问题似乎出在你的初始化上。
正如您声明的那样,
List<ITest> list
不是静态字段。 Main
函数是静态方法,因此只能访问其他静态字段。
如果您想继续这个基本示例,请尝试将
list
设置为静态字段,或设置为 Main
中的变量,并实例化它,在 foreach
循环中使用它之前用一些对象填充它。
关于您的错误,看起来
list
没有实例化,它是一个实例字段,是从静态方法访问的。
接口不是为了继承,而是为了多态性。
接口不是用来保存代码的。如果您需要这样做,请使用抽象类。
接口所做的一切就是向编译器保证您的类将以特定方式运行。 它没有指定任何有关实施的内容。
例如,
List
和LinkedList
的实现方式不同,但它们都符合IEnumerable
接口,因此可以在foreach
循环中迭代
接口的用法是为对象定义类似占位符的东西,它肯定会有一些特定的行为,但实际上并不知道它。例如,您可以有类 A 和类 B,它们都实现 IMyInterface。如果您需要 IMyInterface 的实例,您可以同时使用它们并调用接口中指定但在 A 或 B 中实现的方法。IoC 容器中的接口也有很好的基于约定的用法。