一般来说,某些接口和接口的含义是什么?

时间:2014-10-04 08:01:08

标签: c# interface idisposable

我正在查看一些接口实现,因为我无法使用'using'关键字来确保在C#中正确处理FileInfo对象,但编译器给了我这个错误:

  

'System.IO.FileInfo':在using语句中使用的类型必须可以隐式转换为'System.IDisposable'

因此,我开始记录这些特定接口的实现。

我最终看到所有这些都减少了输入:类名旁边的IDisposable并自己添加Dispose()方法,这就是你如何制作IDisposable。

第一个问题:

这是什么意思?框架创建者不应该制作那些项目 - 一次性/可空/任何你想要的常用界面 - 而不必担心它吗?

我作为一名程序员工作了2年,但我作为一个业余爱好多年,我从未理解为什么界面有用或者它们的目的是什么。它们实际上对我来说似乎毫无用处。

据我所知,他们的唯一目的是作为“契约”,这是我从未完全理解的定义。人们喜欢nto说contrat,虽然他们可以说“它只是意味着你必须重新实现你继承的类的所有方法,即使你把它们变成空”,而不是那种尴尬的“契约”定义。

无论如何,为什么?为什么我需要编译器告诉我需要实现这些方法?我想我永远不会那样。

通常我会在编码时抓住学习或使用它们的概念,但我发誓我从来没有找到或看到过我和我的同事,这种情况下界面很有用,需要,一个很好的选择或方便的东西......

我想即使我看到人们经常使用它们,我也会永远不会使用它们......为什么?

3 个答案:

答案 0 :(得分:1)

与许多其他语言一样,C#不支持多重继承。例如,请参阅the Diamond Problem

在任何情况下,接口都是C#通过避免一些随之而来的问题来接近多重继承的方法。如果Class A有一个名为Foo()的方法而且Class B也有一个名为Foo()的方法,那么当你从两个方法派生出来时,你怎么能解决哪个方法?接口指定 和对象可以做什么,但不能

考虑IList<T> - 表示可扩展列表的集合的通用形式。它有AddRemoveClear等方法。如果有人使用您的课程,他们不应该需要担心您的实施细节,只有它有效。因此,在引擎盖下,您可以拥有List<int>LinkedList<int>,它仍然可以为您的客户提供相同的功能,因为您只为他们公开了interace - 基本合同使用

答案 1 :(得分:0)

毫无疑问,您将使用接口。事实上,如果您正在编写using语句,那么您已经使用了一个语句。

using语句的要点是创建一个对象并确保它在块的末尾暴露。为了能够处置对象,它必须具有Dispose方法。这就是IDisposable界面的来源。

IDisposable接口定义Dispose方法。任何实现IDisposable的类都签署了一个实现该Dispose方法的契约。 using语句要求对象具有Dispose方法,以便能够在块的末尾处置它,并且它知道该方法存在的方式是您和& #39;重新使用工具IDisposable

这种事情全都可见。编写foreach循环时,循环的对象必须实现IEnumerable。在引擎盖下,foreach循环使用该接口定义的功能来枚举指定的列表。

同样,为了将类似ComboBoxListBoxDataGridView的WinForms控件绑定到数据列表,该列表必须实现IList接口,因为底层数据绑定机制使用该接口定义的功能。

这基本上是接口的作用:它们保证可以使用一组特定的功能。他们没有承诺如何实现该功能或者可能提供或不提供其他功能。

考虑接口如何在其他地方工作。您使用计算机,因此通常可以通过USB接口熟悉它。为了符合USB标准,设备必须提供一组特定的功能。它是如何做到的以及它做的其他事情与计算机上的USB端口无关。只要它有一个合适的USB插头,可以成功发送和接收相应的消息,它就可以工作。

将您的using声明视为IDisposable端口。只要它有一个名为&#34; Dispose&#34;的方法,调用它的Dispose方法或者它有什么其他属性和方法时,对象的作用并不重要。没有参数且不返回任何内容,它可以实现IDisosable并被using语句接受。

答案 2 :(得分:0)

特别关注IDisposable:首先,一次性 nullable 非常不同。

  • 每个引用类型的变量都可以自动为空,这意味着您可以将它们设置为null。您需要为此实现IDisposable
  • 当您实现IDisposable接口时,您这样做是为了释放运行时无法自动释放的资源,或者不应该受到(有些不确定的)垃圾收集的影响。
    例如,您可以编写一个类,其实例打开一个文件并写入文件 - 当不再需要您的类的实例时,应该关闭该文件。然后它应该被关闭(因为那时其他东西可能想要访问该文件),而不是“在不再需要该类之后的某个时刻,最迟在该过程终止时”。因此,您应该声明自己的类来实现IDisposable(因此您的班级用户需要调用Dispose,并且他们也可以在using块中使用您的班级)以关闭文件的方式实现Dispose方法。

现在,正如您所说,接口通常用作“合同” - 保证您的类实现一组特定成员的调用者。因此,简单回答你的问题

  

为什么我需要编译器告诉我需要实现这些方法?

是“所以他们可以被召唤。”

考虑以下示例 - 首先,声明一个接口和两个实现它的类:

public interface ISomeInterface
{
    bool DoSomething();

    int SomeValue { get; }
}

public class Example1 : ISomeInterface
{
    public bool DoSomething()
    {
        return true;
    }

    public int SomeValue {
        get {
            return 42;
        }
    }
}

public class Example2 : ISomeInterface
{
    public bool DoSomething()
    {
        return DateTime.IsLeapYear(DateTime.Now.Year);
    }

    public int SomeValue {
        get {
            return DateTime.Now.Year;
        }
    }
}

现在,让我们添加一个类,该方法返回ISomeInterface的实现:

public class SomeMasterClass
{
    public static ISomeInterface CreateObject()
    {
        if (DateTime.Now.Year % 3 == 0) {
            return new Example1();
        } else {
            return new Example2();
        }
    }
}

根据内部条件,返回Example1的实例或Example2的实例。在调用该方法时,您不知道实际将实例化哪个类,并且您不需要知道 - 因为它们都实现了您要使用其成员的接口

ISomeInterface myObject = SomeMasterClass.CreateObject();
Console.WriteLine(myObject.DoSomething());
Console.WriteLine(myObject.SomeValue);

如果没有界面,SomeMasterClass.CreateObject()的返回值必须输入System.Object(因为这是Example1Example2最专业的共同祖先。 ,由于这两个类都实现了ISomeInterface接口,因而履行了该接口强加的合同,您可以依靠它们为DoSomething方法和{{提供实现1}}属性。