gpt4 book ai didi

C# 如何将泛型可枚举类型参数传递给另一个需要 IEnumerable 的方法?

转载 作者:行者123 更新时间:2023-12-05 04:19:09 25 4
gpt4 key购买 nike

我有一个方法在方法签名中接受一个基本的泛型变量:

public void Foo<T>(T val) {

if (val is IEnumerable) {
Bar(val)
}
}

...Logic if not enumerable

Bar 的签名如下所示:

private void Bar<T>(IEnumerable<T> vals) {
...Logic if enumerable
}

逻辑非常冗长,并且根据传入的项是否可枚举而有所不同。我无法获得 Bar(val)上类。我尝试了以下方法,让我知道我遗漏了什么:

Bar(val)

Bar((IEnumerable<T>)val)(编译,但在尝试使用整数列表时在运行时导致此错误:

Unable to cast object of type 'System.Collections.Generic.List`1[System.Int32]' to type 'System.Collections.Generic.IEnumerable`1[System.Collections.Generic.List`1[System.Int32]]'.'

Bar((IEnumerable)val)

最佳答案

唯一不更改签名和/或使用 dynamic 的选项是潜入反射(reflection)。您需要获取 IEnumerable<TInner> 的封闭通用类型(其中 T : IEnumerable<TInner> ),构建相应的封闭版本 Bar并调用它。沿着这条线的东西:

void Foo<T>(T val)
{
var genericEnumInterface = typeof(T).GetInterfaces()
.FirstOrDefault(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IEnumerable<>));
if (genericEnumInterface is not null)
{
MethodInfo mi = ...; // get Bar via reflection
var constructedMethod = mi.MakeGenericMethod(genericEnumInterface);
constructedMethod.Invoke(this, new[]{(object)val}); // assuming Bar is in the same class as Foo
}
}

请注意,有些类型将实现 IEnumerable<T>你可能不想通过 Bar 处理它喜欢string这是IEnumerable<char> .另一个问题是反射在某些情况下会导致明显的性能下降,因此您可以尝试 caching它(参见例如 thisthis answer )。

另外,我个人会尽量避免使用像 Foo 这样的通用方法。由于可能的误用和极端情况,例如 string .

关于C# 如何将泛型可枚举类型参数传递给另一个需要 IEnumerable 的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74934949/

25 4 0
文章推荐: c# - 为什么 C# Func 不能赋值给 Func