gpt4 book ai didi

c# - 基本泛型接口(interface)上的扩展方法

转载 作者:太空狗 更新时间:2023-10-29 22:53:05 26 4
gpt4 key购买 nike

我正在实现一个流畅的构建器模式,该模式需要在静态扩展方法中接受可枚举并迭代其内容,同时将仿函数应用于可枚举的内容。如(不是实际代码,只是一个例子):

public static IValidator<IEnumerable<T>> Each<T>(
this IValidator<IEnumerable<T>> enumerable,
Func<T, bool> action)
{
foreach (T value in enumerable)
action(value);

return validator;
}

这对于可枚举非常有效,但对于继承的类型/接口(interface)却失败了。比方说:

IValidator<IEnumerable<Guid>> validator = ...;

IEnumerable<Guid> guids = ...;
validator.Each(guids, guid => guid != Guid.Empty); // ok

IList<Guid> guids = ...;
validator.Each(guids, guid => guid != Guid.Empty); // doesn't compile (see below)

异常(exception)情况是:

IValidator<IList<Guid>> does not contain a definition for 'Each' and no extension method 'Each' accepting a first argument of type IValidator<IList<Guid>> could be found (are you missing a using directive or an assembly reference?

我的问题是关于 IValidator<T> 的继承链更具体地说,它的泛型类型参数 T .为什么输入 IValidator<IEnumerable<T>>不可从 IValidator<IList<T>> 分配?我想不出在哪种情况下 IList<T>不是 IEnumerable<T> (给定相同的 T )。

将通用参数限制为 T : IEnumerable<R>确实有效,但这需要两个类型参数( TR ),如果可能的话,我想避免。

有什么想法吗?更好的解决方案?谢谢。

最佳答案

这是由于您的 IValidator<T> 的定义所致界面。我敢打赌,这与以下内容类似:

public interface IValidator<T>

你真正想要的是:

public interface IValidator<out T>

这将使您的界面 covariant ,这意味着您可以分配 IValidator<T2> 的实现至 IValidator<T> ,假设 T2源自 T .

在这种情况下, IList<T> 源自 IEnumerable<T> ,所以你应该能够声明T作为协变。但是,这取决于 IValidator<T> 上的方法以及它们是如何暴露的。

即,如果您在 IValidator<T> 上有方法采用 T 的实例in 作为接口(interface)上任何方法的参数,那么您将无法将接口(interface)声明为协变的。

如果是这种情况,那么您应该能够摆脱 Each 的定义:

public static IValidator<T> Each<T, TValue>(
this IValidator<T> enumerable,
Func<TValue, bool> action) where T : IEnumerable<TValue>
{
foreach (TValue value in enumerable)
action(value);

return validator;
}

这将表明 T应该来自 IEnumerable<TValue> .

关于c# - 基本泛型接口(interface)上的扩展方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12216488/

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