【问题标题】:How to get the C# compiler to infer generic types?如何让 C# 编译器推断泛型类型?
【发布时间】:2009-07-30 19:24:49
【问题描述】:

我有以下方法:

public TResult Get<TGenericType, TResult>()
                          where TGenericType : SomeGenericType<TResult>
                          where TResult : IConvertible {
   //...code that uses TGenericType...
   //...code that sets someValue...
   return (TResult) someValue;
}

现在,这个方法的用户必须像这样使用它:

//Notice the duplicate int type specification
int number = Get<SomeGenericType<int>, int>();

为什么我必须在方法定义中指定 TResult?编译器已经知道 TResult,因为我在 TGenericType 中指定了它。理想情况下(如果 C# 编译器更聪明一点),我的方法应该是这样的:

public TResult Get<TGenericType>()
                          where TGenericType : SomeGenericType<TResult>
                          where TResult : IConvertible {
   //...code that uses TGenericType...
   //...code that sets someValue...
   return (TResult) someValue;
}

所以用户可以像这样简单地使用它:

//Much cleaner
int number = Get<SomeGenericType<int>>();

有没有办法做我想做的事?

【问题讨论】:

  • 我认为从问题描述中删除一些限定词,例如 stupid 会有所帮助。
  • 是编译器傻了,对吧? ;) 我删除了无关的评论。没有它,这实际上是一个合理的问题。
  • 既然您已经回答说没有办法只使用一些类型参数,也许您应该根据您想要完成的内容重新提出您的问题。就目前而言,您的问题是“如何使 C# 编译器编译违反 C# 语言定义的代码?”因此,它应该作为“不是一个真正的问题”来结束。
  • @John 因为很多人都不知道 c# 规范,所以问“有没有办法暗示编译器做我想做的事”是合理的,同样合理的回答是“不,c# 规范不允许这样做。”
  • 我想要完成的事情没有改变。真是糟透了,事情就是这样。我希望他们在未来的 C# 版本中对其进行更改。

标签: c# compiler-construction


【解决方案1】:

C# 规范不允许推断类型参数的一半。您应该让编译器推断所有类型参数(这并不总是适用,就像您的情况一样)或手动指定所有类型参数。

更新(回复评论):虽然我不在 C# 团队中对您的问题给出绝对答案,但我的猜测是重载解决方案的复杂性(这已经是吹;您知道,如果您阅读 C# 规范的那部分),如果他们希望允许推断一半类型而不允许推断一半类型(特别是考虑到您可以仅通过泛型参数的数量重载方法这一事实),将会显着增加。

【讨论】:

  • 但是为什么他们在 C# 规范中指定了这一点?好像没有什么不安全的地方。
  • 查看一些 C++ 规则,包括模板的部分特化以及访问说明符的工作方式。通常事情进展顺利,但这里和那里都潜伏着一些陷阱。由于 Java 和 C# 背后的想法之一是避免 C++ 的复杂性,而是接受一点不便,这是正确的。
【解决方案2】:

这取决于...

如果你只是使用SomeGenericType&lt;TResult&gt;,你可以这样做:

public TResult Get<TResult>() where TResult : IConvertible {
    SomeGenericType<TResult> myInstance = ...
    //...code that sets someValue...
    return (TResult) someValue;
}

在这种情况下,不一定有办法将第一种类型放入其中。由于您的示例没有明确传递 SomeGenericType&lt;TResult&gt; 作为参数,因此表明这是可能的。

否则,您需要完全指定所有通用参数。不幸的是,这正是 C# 中的方式。

【讨论】:

  • 当然,但我确实需要在方法中使用 SomeGenericType。我将更新我的示例代码以明确这一点。
  • 是的,但是看看我的代码——只要不作为参数传入方法,就可以在方法中使用 SomeGenericType (即:如果在方法中构造一个)。既然你知道 TResult,这很好用。正如我所说 - 它可以在某些情况下工作......
  • 抱歉,我的意思是我需要使用 TGenericType(请参阅我更新的示例代码)。
猜你喜欢
  • 2021-08-22
  • 1970-01-01
  • 2011-02-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多