gpt4 book ai didi

c# - 当类型参数为 IEnumerable 时,如何将扩展方法附加到泛型类?

转载 作者:太空狗 更新时间:2023-10-29 21:54:38 25 4
gpt4 key购买 nike

作为一个爱好项目(并让自己更深入地沉浸在泛型/扩展方法中),我正在编写一个参数检查库!

我有一个名为 Argument 的模型,它描述了一个参数,如下所示:

public class Argument<T>
{
internal Argument(string name, T value)
{
Name = name;
Value = value;
}

public string Name { get; private set; }

public T Value { get; private set; }
}

当开始验证参数时,将创建该对象的一个​​实例,并通过调用挂起它的扩展方法(包含实际逻辑)来执行各个验证。

一个这样的扩展方法验证一个集合至少包含一个项目,目前看起来像这样:

public static Argument<IEnumerable<T>> HasItems<T>(this Argument<IEnumerable<T>> argument)
{
if (!argument.Value.Any())
throw Error.Generic(argument.Name, "Collection contains no items.");

return argument;
}

但似乎没有效果。比方说,如果我要编写这个单元测试:

[TestMethod]
public void TestMethod1()
{
var argument = new List<int>() { 1, 2, 6, 3, -1, 5, 0 };

Validate.Argument("argument", argument)
.IsNotNull()
.HasItems()
.All(v => v.IsGreaterThan(0));
}

HasItems 没有出现在 Intellisense 中,并且我得到了这个编译错误:

'Validation.Argument<System.Collections.Generic.List<int>>' does not contain a definition for 'HasItems' and no extension method 'HasItems' accepting a first argument of type 'Validation.Argument<System.Collections.Generic.List<int>>' could be found (are you missing a using directive or an assembly reference?)

如果我尝试将值直接传递给扩展方法,如下所示:

CollectionTypeExtensions.HasItems(Validate.Argument("argument", argument));

我明白了:

The best overloaded method match for 'Validation.CollectionTypeExtensions.HasItems<int>(Validation.Argument<System.Collections.Generic.IEnumerable<int>>)' has some invalid arguments

根据我的研究,我需要的是“变体”,它适用于接口(interface)和委托(delegate),但不适用于类(即:所有类都是不变的。)

也就是说,它可能会以另一种方式工作。想到的一个是重写它以直接转到 T,如下所示:

public static Argument<T> HasItems<T, TElement>(this Argument<T> argument)
where T : IEnumerable<TElement>
{
if (!argument.Value.Any())
throw Error.Generic(argument.Name, "Collection contains no items.");

return argument;
}

..但这也不起作用,因为它需要在调用方法时明确指定 TElement。我也可以回退到在类型约束中使用非通用 IEnumerable 接口(interface),但是我必须找到一种方法将 IEnumerable 强制转换为 IEnumerable(这需要知道 T 在该上下文中是什么),或者复制Any() 的功能是为了测试任何项目的存在, 还有另一种扩展方法 (All),这会非常非常困惑,所以我宁愿避免它。

所以最终,我想我的问题是:如何让我的扩展方法正确附加?

最佳答案

这对你有用吗?看起来有点笨拙,但它确实有效。

public static Argument<T> HasItems<T>(this Argument<T> argument) where T: IEnumerable
{
if (!argument.Value.Cast<object>().Any())
{
throw Error.Generic(argument.Name, "Collection contains no items.");
}

return argument;
}

关于c# - 当类型参数为 IEnumerable<T> 时,如何将扩展方法附加到泛型类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15183471/

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