繁体   English   中英

使用IList进行C#重载解析 <T> 和IReadOnlyList <T>

[英]C# overload resolution with IList<T> and IReadOnlyList<T>

我有一个方法,我想在我的解决方案中采取所有类似列表的对象。 在.NET 4.5之前,这很简单:

public static T Method<T>(IList<T> list)
{
    // elided
}

但是,.NET 4.5引入了IReadOnlyList<T> ,该方法也应该适用于此。

我不能只改变签名来获取IReadOnlyList<T> ,因为有些地方我将这个方法应用于特定类型的IList<T>

该算法不能在IEnumerable<T>上运行,并且它太频繁地使用(并且对象太大)来获取IEnumerable<T>并在每次调用时创建一个新的List<T>

我试过添加一个重载:

public static T Method<T>(IReadOnlyList<T> list)
{
    // elided
}

...但是这不能编译实现两个接口( T[]List<T>和许多其他类型)的任何东西,因为编译器无法确定使用哪种方法(特别烦人,因为它们具有相同的身体,所以没关系)。

我不想添加带有T[]List<T>Method重载,以及实现这两个接口的所有其他类型。

我该怎么做到这一点?

这可能是实际检查运行时类型有用的场合之一:

public static T Method<T>(IEnumerable<T> source)
{
    if (source is IList<T> list)
        return Method(list);

    if (source is IReadOnlyList<T> readOnly)
        return Method(readOnly);

    return Method(source.ToList() as IList<T>);
}

private static T Method<T>(IReadOnlyList<T> list) { ... }
private static T Method<T>(IList<T> list) { ... }

您仍然需要复制代码,因为您需要为IListIReadOnlyList单独实现,因为没有可以利用的通用接口,但您至少可以避免出现模糊的调用问题。

您可能最好的选择是进行全局搜索并将IList替换为IReadOnlyList 如果没有编译器错误,那么你应该没问题。

如果您使用的是IList.Add ,那么您应该只收到编译器错误 - 无论如何这都是IList.Add ,因为数组不支持Add

你能改变方法调用的代码吗? 如果您创建这样的方法怎么办:

    public static T1 Method<T1, T2>(T2 list) where T2 : IList<T1>, IReadOnlyList<T1>
    {
        return default(T1);
    }

在这种情况下,调用如下所示:

List<string> listA = new List<String>();
ReadOnlyCollection<string> listB = listA.AsReadOnly();

string outVar1 = Method<string, List<string>>(listA);
string outVar2 = Method<string, ReadOnlyCollection<string>>(listB);

以这种方式为IList和IReadOnlyList创建两个扩展方法的另一种方法:

    public static T Test<T>(this IList<T> source)
    {
        return default(T);
    }

    public static T Test<T>(this IReadOnlyList<T> source)
    {
        return default(T);
    }

并称他们为:

    string outVar1 = (listA as IReadOnlyList<string>).Test();
    string outVar2 = (listB as IList<string>).Test();

也许你最好的解决方案是调查为什么你的算法无法在IEnumerable上运行并改变它。 您是否正在使用IList<T>IReadOnlyList<T>特定成员,您可以使用IEnumerable<T>可用的成员替换它们? 例如:

// instead of
int c = list.Count;

// use
int c = list.Count();

编辑:忽略下面的废话。 我要离开它,以便评论继续有意义。

您不应该在任何类中实现IList<T>IReadOnlyList<T> IList规范中唯一的附加成员是写入列表。 如果您的列表是只读的,则不需要这样做。 我认为您需要更改任何实现两者的类,以便在使用它们时可以选择正确的方法。

但是,由于IReadOnlyList<T>所有成员都包含在IList<T> (以及从IReadOnlyCollection<T>派生的那些成员),我想知道.Net中的IList<T>是否应该实际更改,以便它继承IReadOnlyList<T>界面而不是复制成员。 这并不是说现在有所帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM