我的最终目标是获得一个可以采用任何其他功能的功能 - 例如
void RegisterHandler( Delegate function);
但是 - 我希望能够在不进行任何转换或没有类型参数的情况下调用它 - 显然 Delegate 不起作用。如果我声明:
void RegisterHandler<T>( Func<T> function );
然后它工作正常 - 这工作:
string Whatever() {return "hi";}
...
RegisterHandler( whatever );
但是 - 一旦我输入参数,它就不起作用
void RegisterHandler<TParam1,TReturn>( Func<TParam1, TReturn> function );
string Something( int x ) {return x.ToString();}
...
RegisterHandler( Something ); // doesn't compile - wants types specified
RegisterHandler<int,string>( Something ); // works, but is what I'm trying to avoid
如果“对象”有效,我什至可以 - 这只是流畅界面的一部分,我只想能够调用它。我在某处读到参数的数量必须> =模板类型的数量,并且我猜返回类型被计算在内,所以我永远无法实现。
底线 - 我找不到任何可以接受任何接受一个参数并返回一些东西的函数的 c# 签名。是否可以?
最佳答案
与其直接攻击你的问题,这需要一些澄清,让我在这里解决你的担忧:
I read somewhere that the number of parameters has to be >= the number of template types
让我们把它清脆一点。
首先,这些是泛型类型参数,而不是“模板类型”。这不是 C++。泛型类似于模板,但它们不是模板,越早停止将它们视为模板越好。
形式参数的数量需要大于或等于泛型方法声明的泛型类型参数的数量是不正确的。例如:
static void M<K, V>(Dictionary<K, V> d) { }
...
Dictionary<int, string> d = whatever;
M(d); // No problem!
形参的个数是一个,泛型类型参数的个数是两个,但是我们这里做类型推断是没有问题的。
真正的规则要复杂得多。相反,您遇到的真正问题是:
方法组到委托(delegate)的转换要求在转换发生之前知道委托(delegate)的参数类型 .
假设我们有:
int F(string x) { ... }
void M<A, R>(Func<A, R> f) { ... }
M(F);
发生什么了?我们必须确定 F 转换为
Func<A, R>
时的含义。但我们都不知道A
也不是 R
.我们如何确定意义? 我们做重载决议 .也就是说,我们会假装有一个电话:A a = whatever;
F(a)
并问“哪种名为 F 的方法可行?”
但是我们甚至没有走到那一步,因为我们不知道
A
还没有。类型推断未能取得进展。现在,如果相比之下你有:int F(string x) { ... }
void M<A, R>(A a, Func<A, R> f) { ... }
M("abc", F);
现在类型推断首先说“我从
"abc"
的使用中推断出 a
的 A
是 string
。”在做出该推断之后,现在重载解决方案将成功。如果我们这样做了string a = whatever;
F(a);
那么重载决议将确定
F
表示 int F(string)
.一旦我们确定
F
表示 int F(string)
,现在我们可以问一个问题“关于从 int F(string)
到 Func<string, R>
的转换,我们可以推断出什么,并由此推断 R
必须是 int
,我们就完成了。我知道你接下来要问什么。 我只有一个称为 F 的重载,那我们为什么不自动选择它呢?
做出这样的异常(exception)有很多问题。首先,特殊情况往往会成倍增加,很快我们就会有一个更疯狂的推理算法,没有人理解,并且无法在不引起错误的情况下更改它。其次,它使你的代码变得脆弱;这意味着推理取决于范围内名为 F 的可访问方法的数量。假设您添加了一个新的私有(private)方法,也称为
F
;推理会突然改变吗?不,一旦你知道了这条规则,它就很简单易懂。 方法组的解析与调用方法 完全相同。 .但是在推断出参数类型之前,我们无法模拟调用。
相信我,我和任何人一样都知道 C# 中的类型推断算法有多么棘手;它有很多这类令人惊讶的案例。如果您对此算法的设计、实现或规范有更明确的问题,请随时提出一个新问题,并对这个答案发表评论,我会尝试看看。
关于c# - C#中的make方法,它接受没有类型参数的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61375152/