我正在查看一些接口实现,因为我无法使用'using'关键字来确保在C#中正确处理FileInfo对象,但编译器给了我这个错误:
'System.IO.FileInfo':在using语句中使用的类型必须可以隐式转换为'System.IDisposable'
因此,我开始记录这些特定接口的实现。
我最终看到所有这些都减少了输入:类名旁边的IDisposable并自己添加Dispose()方法,这就是你如何制作IDisposable。
第一个问题:
这是什么意思?框架创建者不应该制作那些项目 - 一次性/可空/任何你想要的常用界面 - 而不必担心它吗?
我作为一名程序员工作了2年,但我作为一个业余爱好多年,我从未理解为什么界面有用或者它们的目的是什么。它们实际上对我来说似乎毫无用处。
据我所知,他们的唯一目的是作为“契约”,这是我从未完全理解的定义。人们喜欢nto说contrat,虽然他们可以说“它只是意味着你必须重新实现你继承的类的所有方法,即使你把它们变成空”,而不是那种尴尬的“契约”定义。
无论如何,为什么?为什么我需要编译器告诉我需要实现这些方法?我想我永远不会那样。
通常我会在编码时抓住学习或使用它们的概念,但我发誓我从来没有找到或看到过我和我的同事,这种情况下界面很有用,需要,一个很好的选择或方便的东西......
我想即使我看到人们经常使用它们,我也会永远不会使用它们......为什么?
答案 0 :(得分:1)
与许多其他语言一样,C#不支持多重继承。例如,请参阅the Diamond Problem。
在任何情况下,接口都是C#通过避免一些随之而来的问题来接近多重继承的方法。如果Class A
有一个名为Foo()
的方法而且Class B
也有一个名为Foo()
的方法,那么当你从两个方法派生出来时,你怎么能解决哪个方法?接口指定 和对象可以做什么,但不能 。
考虑IList<T>
- 表示可扩展列表的集合的通用形式。它有Add
,Remove
和Clear
等方法。如果有人使用您的课程,他们不应该需要担心您的实施细节,只有它有效。因此,在引擎盖下,您可以拥有List<int>
或LinkedList<int>
,它仍然可以为您的客户提供相同的功能,因为您只为他们公开了interace - 基本合同使用。
答案 1 :(得分:0)
毫无疑问,您将使用接口。事实上,如果您正在编写using
语句,那么您已经使用了一个语句。
using
语句的要点是创建一个对象并确保它在块的末尾暴露。为了能够处置对象,它必须具有Dispose
方法。这就是IDisposable
界面的来源。
IDisposable
接口定义Dispose
方法。任何实现IDisposable
的类都签署了一个实现该Dispose
方法的契约。 using
语句要求对象具有Dispose
方法,以便能够在块的末尾处置它,并且它知道该方法存在的方式是您和& #39;重新使用工具IDisposable
。
这种事情全都可见。编写foreach
循环时,循环的对象必须实现IEnumerable
。在引擎盖下,foreach
循环使用该接口定义的功能来枚举指定的列表。
同样,为了将类似ComboBox
,ListBox
或DataGridView
的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
(因为这是Example1
和Example2
最专业的共同祖先。 ,由于这两个类都实现了ISomeInterface
接口,因而履行了该接口强加的合同,您可以依靠它们为DoSomething
方法和{{提供实现1}}属性。