【问题标题】:Can the compiler infer object Type when omitted in method call?在方法调用中省略时编译器可以推断对象类型吗?
【发布时间】:2012-02-04 09:26:30
【问题描述】:

考虑以下情况:

public class Storage
{
 public T GetSingleByID<T>(long id) where T : IStorable
 {
  // do some magic to return the object based on T and the id
 }
}

public class Beer : IStorable
{
}

public class BeerStorage : Storage
{
}


BeerStorage beerStorage = new BeerStorage();
Beer beer = beerStorage.GetSingleByID(5); /* compile error here */

由于无法推断类型,我得到一个编译错误,原因很明显。很公平。但是有没有办法让编译器能够根据我在BeerStorage而不是Storage上调用GetSingleByID这一事实来推断正确的类型?我想说编译器应该有一种方法可以看到这种差异并为我推断 T?

如何在BeerBeerStorage 之间建立关系,以便编译器可以推断出正确的类型?

【问题讨论】:

  • 我可以看到BeerBeerStorage 之间没有任何关系。将您的 beer 变量声明为 Beer 在这里并没有真正的帮助......
  • @BoltClock,是的,我知道BeerBeerStorage 之间没有关系,这会导致编译错误。我的问题是,如何建立这种关系?提前致谢。
  • @delnal,不,显然这行不通。但基于其他一些我可能不知道的事情。你能告诉我你将如何解决这个问题吗?谢谢。
  • 你应该从Storage&lt;Beer&gt;派生BeerStorage

标签: c# generics


【解决方案1】:

最简单的方法是在 Storage 类上声明泛型类型参数和约束,而不是在其 GetSingleByID() 方法上:

public class Storage<T> where T : IStorable
{
 public T GetSingleByID(long id)
 {
  // do some magic to return the object based on T and the id
 }
}

然后将其扩展为BeerStorage,并将Beer 作为泛型类型,如下所示:

public class BeerStorage : Storage<Beer>
{
}

然后您的调用代码应该可以工作了。您甚至可以将Beer 声明切换为var 关键字,编译器将知道BeerStorage.GetSingleByID() 返回一个Beer 实例:

BeerStorage beerStorage = new BeerStorage();
var beer = beerStorage.GetSingleByID(5); /* beer is a Beer instance */

【讨论】:

  • 我对泛型的(有限)知识的简单差距。我不知道你可以在类上指定泛型类型参数。完美的解决方案!将在时间段到期后接受答复。
  • @CodeInChaos:感谢您的编辑——我的 copypasta 过程显然需要查看 ;)
  • 我一开始也犯了同样的错误。所以当我编辑我的答案来修复它时,我注意到你犯了和我一样的复制粘贴错误。
【解决方案2】:

C# 不会从返回值推断泛型参数。所以你的代码不起作用。如果您想保留当前代码,则需要在每个呼叫站点 Beer beer = beerStorage.GetSingleByID&lt;Beer&gt;(5); 处指定 T

我将Storage 设为通用,然后在定义BeerStorage 类时将Beer 替换为T 进行专门化:

public class Storage<T>
  where T : IStorable
{
 public T GetSingleByID(long id) 
 {
  // do some magic to return the object based on T and the id
 }
}

public class Beer : IStorable
{
}

public class BeerStorage : Storage<Beer>
{
}

【讨论】:

  • +1 事实上,这是正确的方法,正如 BoltClock 所建议的那样。谢谢你的回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-10
  • 1970-01-01
  • 2021-08-22
  • 1970-01-01
  • 1970-01-01
  • 2018-08-22
相关资源
最近更新 更多