我有一个几乎没有通用重载方法的类。我试图通过其参数类型获得特定的一个。当我坚持前两个(带有int和string类型的参数)时,它相对容易做到。但无论我做什么,我都无法让我的程序注意到第三个,用于通用列表。我使用了错误的Type参数吗?如果是这样,什么是正确的方法?
/* rest of code */
static void Main(string[] args) {
MethodInfo method =
typeof(c).GetMethod("m", new Type[] { typeof(int) });
Console.WriteLine(method);
method =
typeof(c).GetMethod("m", new Type[] { typeof(String) });
Console.WriteLine(method);
method =
typeof(c).GetMethod("m", new Type[] { typeof(IEnumerable<>) });
Console.WriteLine(method);
Console.ReadKey();
}
}
static class c
{
public static void m<T>(int i)
{
}
public static void m<T>(String s)
{
}
public static void m<T>(IEnumerable<T> Ls)
{
}
}
答案 0 :(得分:1)
简短版本:typeof(IEnumerable<>)
与typeof(IEnumerable<T>)
不同(对于某些T
)。
更长的版本:没有方法void c.m(IEnumerable<> Ls)
,只有通用参数特定的重载 - 在运行时存在 - 由于某些代码引用实例化而导致创建方法所需的抖动类型通用方法。
在测试代码中添加一个调用泛型方法的某个实例,然后为该实例执行GetMethod
。
请考虑以下事项:
using System.Collections.Generic;
using System.Linq;
using static System.Console;
class Methods {
public static void M(int x) {
// no-op
}
public static void M<T>(IEnumerable<T> x) {
// no-op
}
}
class Program {
static void Main(string[] args) {
Methods.M(0);
Methods.M(new[] { "a", "b" });
ShowAllM();
}
public static void ShowAllM() {
var tm = typeof(Methods);
foreach (var mi in tm.GetMethods().Where(m => m.Name == "M"))
{
WriteLine(mi.Name);
foreach (var p in mi.GetParameters())
{
WriteLine($"\t{p.ParameterType.Name}");
}
}
}
}
产生输出:
M Int32 M IEnumerable`1
请注意,泛型重载只有一个结果。如果M<char>(…)
的{{1}}被添加到Main
,则输出相同。
对于反射,只有一种方法,它的参数反映了它的“开放通用”性质,但这与使用开放泛型类型(例如。IEnumerable<>
)可调用的开放类型不完全相同不可实例化。
(我在这里捏造了大部分技术细节。在typeof(IEnumerable<>)
和typeof(IEnumerable<int>)
之间查看调试器的区别是有用的。)
答案 1 :(得分:1)
第三种方法的签名为m<T>(IEnumerable<T>)
,但您的示例显示了尝试查找带有签名m(IEnumerable<>)
的方法。
typeof(IEnumerable<T>)
和typeof(IEnumerable<>)
之间的区别是前者是泛型类型,第二种是泛型类型定义,这些不是同一个东西。泛型类型由泛型类型定义和泛型类型参数确定。
考虑到这一点,你会想要使用:
method =
typeof(c).GetMethod("m", new Type[] { typeof(IEnumerable<MyType>) });
并替换您将传递给方法的枚举类型。
另一方面,如果你不知道前面可枚举的类型,你可以得到泛型方法定义,并在需要时制作可用的泛型方法:
methodDef =
typeof(c).GetMethod("m", new Type[] { typeof(IEnumerable<object>) }).GetGenericMethodDefinition();
method = methodDef.MakeGenericMethod(new Type[] { typeof(MyType) });
答案 2 :(得分:0)
如果从int和string方法中删除通用defenitions:
return RxTextView.textChanges(editText).switchMap(charSequence ->
realm.where(Dog.class)
.contains(DogFields.NAME, charSequence.toString())
.findAllAsync()
.asObservable()
).filter(RealmResults::isLoaded)
.subscribe(dogs -> {
adapter.updateData(dogs);
});
并使用以下行来获得所需的通用方法:
public static void m(int i)
{
}
public static void m(String s)
{
}
public static void m<T>(IEnumerable<T> Ls)
{
}
这样就可以了解