gpt4 book ai didi

c# - 为什么List要使用显式接口(interface)方法实现来实现非泛型接口(interface)方法?

转载 作者:行者123 更新时间:2023-12-02 02:21:57 25 4
gpt4 key购买 nike

// Some interface method signature

public interface IList : ICollection {
...
bool Contains(Object value);
...
}

public interface IList<T> : ICollection<T> { ... }

public interface ICollection<T> : IEnumerable<T> {
...
bool Contains(T item);
...
}

List源码如下:https://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs

public class List<T> : IList<T>, System.Collections.IList, IReadOnlyList<T> {
...
public bool Contains(T item) {
...
}

bool System.Collections.IList.Contains(Object item) {
...
}
}

可以看到List使用显式接口(interface)方法实现(显式指定接口(interface)名称)来实现非泛型Contains。但我对显式接口(interface)方法实现的了解是,只有当有两个接口(interface)方法具有相同的签名时,你才会这样做。

但是对于public bool Contains(T item)public bool Contains(Object item),它们是不同的方法,因为它们有不同的签名(通用参数和非-通用参数),因此 List 将被实现为:

public class List<T> : IList<T>, System.Collections.IList, IReadOnlyList<T> {
public bool Contains(T item) { ... }

public bool Contains(Object item) { ... }
}

那为什么List要使用显式接口(interface)方法实现来实现非泛型接口(interface)方法呢?我看不出在这种情况下使用显式接口(interface)方法实现有任何好处。我在这里遗漏了什么吗?

最佳答案

You can see that List uses explicit interface method implementation (explicitly specify the interface's name) to implement the non-generic Contains

确实。

但那是因为 IList 接口(interface)(不是 IList<T> )已经有几十年的历史了——从 .NET 支持泛型之前的原始、黑暗时代开始(.NET 1.0 于 2001 年问世——泛型直到 .NET 才被添加2005 年的框架 2.0)。那真是一个被上帝遗弃的时代。

List<T>(但不是 IList<T>)实现了 IList 接口(interface),这样新的通用 List<T> 可以被接受 IList 的旧代码使用(以一种允许保留对象标识并且不需要分配单独的 IList 实例)。

假设现在是 2005 年,您正在编写一些奇妙的 C# 2.0 代码,这些代码使用了奇特的新具体化泛型和 List<T> - 但您需要与上次更新于 2004 年的库进行交互:

public void YourNewSexyGenericCode()
{
List<String> listOfString = new List<String>() { "a", "b", "c" };

OldAndBustedNET10CodeFrom2004( listOfString ); // <-- This works because List<String> implements IList.

foreach( String s in listOfString ) Console.WriteLine( s );
}

public void OldAndBustedNET10CodeFrom2004( IList listOfString )
{
listOfString.Add( "foo" );
listOfString.Add( "bar" );
listOfString.Add( "baz" );
return;
}

如果 List<T> 没有实现 IList 那么你将不得不做这样可怕的事情:

    List<String> listOfString = new List<String>() { "a", "b", "c" };

// Step 1: Create a new separate IList and copy everything from your generic list into it.
IList classicList = new ArrayList();
classicList.AddRange( listOfString );

// Step 2: Pass the IList in:
OldAndBustedNET10CodeFrom2004( classicList );

// Step 3: Copy the elements back, in a type-safe manner:
foreach( Object maybeString in classicList )
{
String asString = maybeString as String; // The `is String str` syntax wasn't available back in C# 2.0
if( asString != null )
{
listOfString.Add( asString );
}
}

// Step 4: Continue:
foreach( String s in listOfString ) Console.WriteLine( s );

But what I know about explicit interface method implementation is, you only do it when there are two interface methods that have the same signature.

你错了。除了实现冲突的接口(interface)(例如隐藏 internal 接口(interface)的实现,为兼容性原因(如 IList )和美学原因(减少 API 困惑,尽管 EditorBrowsable 应该用于此目的)。

But for public bool Contains(T item) and public bool Contains(Object item), they are different methods because they have different signatures (generic parameter and non-generic parameter), so List would have been implemented as...

在上面的段落中,我注意到 IList 是一个type-theoretic unsound 接口(interface),即:它允许你做无意义和/或有害的事情,因为示例:

List<String> listOfString = new List<String>() { "a", "b", "c" };
IList asIList = listOfString;
asIList.Add( new Person() );

编译器会让这种情况发生,但它会在运行时崩溃,因为 List<String> 不能包含 Person 。由于 .NET 对协变和逆变的支持,这可以通过具体化的泛型解决(这就是为什么您可以安全地将任何 List<String> 隐式转换为 IEnumerable<Object> 的原因,因为 String : Object ,即使 List<T> 确实如此实际上并没有实现 IEnumerable<Object> ,但它确实实现了 IEnumerable<T> )。

Then why does List use an explicit interface method implementation to implement non-generic interface methods?

因为 IList 是一个糟糕的接口(interface),今天没有人应该使用,但由于遗留兼容性要求,有些人被迫使用它。每个人都希望看到这些遗留接口(interface)消失(尤其是我自己),但我们不能,因为它会破坏二进制应用程序的兼容性,这对于任何运行时或平台在 SWE 生态系统中生存都是必不可少的(这也是为什么 .NET 团队不幸的是拒绝许多有意义但会破坏现有编译程序的频繁请求(例如使 IList<T> 扩展 IReadOnlyList<T>)。

I cannot see any benefit to use explicit interface method implementation in this scenario. Am I missing something here?

错过了一些东西 - 我希望我的回答能启发您的想法。

关于c# - 为什么List要使用显式接口(interface)方法实现来实现非泛型接口(interface)方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66286379/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com