2010-05-13 43 views
7

由于我是c#的新手,想了解c#中的接口和委托,它们之间的区别以及这些方案都将被使用。请不要提供任何链接,我想用简单的话来解释。c#中的接口和委托是什么?

+0

相间的代码?你的意思是界面? – kennytm 2010-05-13 07:47:27

+0

我的道歉,它的接口。 – Anuya 2010-05-13 07:51:03

+0

@karthik如果您告诉我们您已熟悉哪些编程语言,它可能会有所帮助。然后,我们可能会将接口和代表与您已熟悉的概念联系起来。 – 2010-05-13 08:16:20

回答

8

Cuts in Nutshell引用。

一个代表可以解决的问题也可以通过一个接口来解决。例如,下面介绍如何使用 的ITransformer接口,以解决我们的过滤问题:

public interface ITransformer 
{ 
    int Transform (int x); 
} 
public class Util 
{ 
    public static void TransformAll (int[] values, ITransformer t) 
    { 
     for (int i = 0; i < values.Length; i++) 
     values[i] = t.Transform (values[i]); 
    } 
} 

class Squarer : ITransformer 
{ 
    public int Transform (int x) { return x * x; } 
} 

... 
static void Main() 
{ 
    int[] values = { 1, 2, 3 }; 
    Util.TransformAll (values, new Squarer()); 
    foreach (int i in values) 
     Console.WriteLine (i); 
} 

委托设计可能比一个接口设计,如果一个或多个 这些条件更好的选择:

  • 该接口仅定义了一个单一的 方法。
  • 需要组播能力。
  • 用户需要多次实现接口 。

在ITransformer示例中,我们不需要多播。但是,接口 仅定义了一种方法。此外,我们的用户可能需要多次实施IT变压器,以支持不同的变换,例如正方形或立方体。 使用接口,我们被迫为每个转换写入一个单独的类型,因为测试 只能实现ITransformer一次。这是非常麻烦

class Squarer : ITransformer 
{ 
    public int Transform (int x) { return x * x; } 
} 
class Cuber : ITransformer 
{ 
    public int Transform (int x) {return x * x * x; } 
} 
... 
static void Main() 
{ 
    int[] values = { 1, 2, 3 }; 
    Util.TransformAll (values, new Cuber()); 
    foreach (int i in values) 
    Console.WriteLine (i); 
} 

这里是代表

public delegate int Transformer (int x); 
class Util 
{ 
    public static void Transform (int[] values, Transformer t) 
    { 
     for (int i = 0; i < values.Length; i++) 
     values[i] = t (values[i]); 
    } 
} 
class Test 
{ 
    static void Main() 
    { 
     int[] values = { 1, 2, 3 }; 
     Util.Transform (values, Square); // Dynamically hook in Square 
     foreach (int i in values) 
     Console.Write (i + " "); // 1 4 9 
    } 
    static int Square (int x) { return x * x; } 
} 
11

接口是一个契约 - 它定义了任何实现类必须拥有的方法和属性,因此接口的任何使用者都知道它们存在并可以使用它们。

委托是一个回叫站点 - 它定义了一个方法签名,可以调用具有相同签名的任何方法。

请参阅C#编程指南中的delegatesinterfaces

接口的一个例子是接口IEnumerable。它只定义了一个成员 - GetEnumerator。任何实现这个接口的对象都有这个方法,任何使用这个对象的代码都可以调用这个方法。

代表的一个示例是Predicate<T>委托。它是一个通用委托即定义如下:

public delegate bool Predicate<in T>(T obj); 

这意味着它需要在任何类型的T和返回一个bool。任何采用单个类型参数并返回bool的方法都可以与此代理匹配,并且可以与它一起使用。

由于委托也是对象,因此可以将它们传递给函数。因此,任何具有Predicate<T>委托的功能都可以通过与其匹配的任何方法。许多Linq运营商都将代表作为参数。见示例here

+0

我需要使用这两种场景..thnx – Anuya 2010-05-13 07:51:46

+2

@karthik - 你为什么不在你的问题中这么说? – Oded 2010-05-13 07:52:53

2

接口是绑定到单个对象的方法的集合。 (注意:对象可能会暴露多个接口,从而使它们展现出多个“个性”)。

委托是单个方法调用的抽象。调用委托具有调用其他代码的效果,调用者对此不知道任何代码。

有些过于简单的东西仍然给人一种风味的观点,就是将代表想象成一个接口的特例,只有一种方法。

5

一个接口可以被认为是一个功能定义(或合同)。在现实世界中,许多对象具有众所周知的接口,使它们在很大程度上(但不完全)可互换。

例如,坐车。一旦你学会了如何驾驶汽车,你将学习“汽车驾驶界面”。你知道将会有一个Accelerate()函数和一个Stop()函数,并且通常是一个ShiftGears()函数(即使它只是将它从停车并放入驱动器中)。还有一个Steer()函数和一个SignalTurn()函数。

不能保证任何给定的实现都会以相同的方式进行操作。例如,丰田可能在CarDriving接口中有一个“Stop()”方法,实际上它会调用Accelerate()。

汽车可能支持其他界面,如SeatBelt界面或Radio界面。尽管这些对象的每个实现可能不同,但总是有一组核心的功能在所有类型的这些对象中都是通用的。这使得它们可以在很大程度上互换使用,而无需重新学习不同的界面。

C#中的接口类似。不同的对象实现可能包含相同的接口实现,并且它们的作用可能不同,但是您可以像实现同一接口一样处理实现特定接口的另一个对象。

如果你明白什么是继承,那么另一种认为接口的方式是它们和一个类相同,但它们没有实现。所以当一个类从另一个类继承时,它继承了“inteface”类和它的“实现”。如果一个类只监听一个接口,那么它缺少一个实现,新类必须自己创建该实现。

一个代表,是完全不同的。一个委托(除其他外)是一个对象感知的函数指针。函数指针是一个变量,类似于其他变量,但它的类型是“委托”而不是“int”或“string”。而且,它不保存数据,而是保存一个指向方法的指针(以及一些状态信息),以便在运行时动态调用不同的函数。

在下面的代码中,对“foo”的调用是固定的。你不能在运行时,决定要叫“巴”而不是:

DoSometing() 
{ 
    foo(); 
} 

相反如果你不喜欢的东西下面,然后你可以通过不同的方法作为参数传递给你的方法,并把它dynically给他们打电话:

DoSomething(MyFunction func) 
{ 
    MyFunction myfunc = func; 
    myfunc(); 
} 

委托人可以做的不止这些,但这是一个基本的想法。

3

好的,我可以用英语与你交谈。你是人类。我可以用英语与任何人交谈;我不需要知道地球上的所有人都可以用英语对他们说话;我所关心的只是他们说英语。

好的,人是一个物体。英文是界面。

很多人类实现了接口IEnglish

现在将其应用于经典工程意义上。我有一辆汽车和一辆汽车电池。这款车并不关心电池的种类,制造地点或形状。 电池不关心汽车。它们在功能上是相互抽象的。

电池供电并实现接口IBattery。汽车只接受实施IBattery的物体(即物理物体是汽车电池!!)

从语义上讲,接口和代表在很大程度上是等效的。一个接口定义了一个对象的作用(方法和属性)...并且一个委托定义了特定方法的作用。代表声明一个函数或方法的参数....他们是类型安全的函数指针。我需要更多的思考才能为此提供一个真实生活的例子。