无效的C#generics?

我有一个通用的方法,接受请求并提供响应。

public Tres DoSomething<Tres, Treq>(Tres response, Treq request) {/*stuff*/} 

但是我并不总是希望得到我的请求的响应,而且我也不总是希望提供请求数据来获得响应。 我也不想全部复制和粘贴方法做一些小改动。 我想要的是能够做到这一点:

 public Tre DoSomething<Tres>(Tres response) { return DoSomething<Tres, void>(response, null); } 

这在某种程度上是可行的吗? 看来专门使用void不起作用,但我希望能find类似的东西。

你不能使用void ,但是你可以使用object :这有点不方便,因为你的void函数需要返回null ,但是如果它统一了你的代码,它应该是一个小的代价。

这种无法使用void作为返回types至less部分负责generics委托的Func<...>Action<...>系列之间的分割:是否有可能返回void ,所有的Action<X,Y,Z>将变成简单的Func<X,Y,Z,void> 。 不幸的是,这是不可能的。

不,不幸的不是。 如果void是一个“真实”的types(比如F#中的unit ),那么在很多方面,生活将会变得简单得多。 特别是,我们不需要Func<T>Action<T>系列 – 只需要Func<void>而不是ActionFunc<T, void>而不是Action<T>等。

这也会使asynchronous更简单 – 根本就不需要非通用的Tasktypes – 我们只需要Task<void>

不幸的是,这不是C#或.NETtypes系统的工作方式。

这是你可以做的。 正如@JohnSkeet所说,C#中没有单元types,所以自己动手!

 public sealed class ThankYou { private ThankYou() { } private readonly static ThankYou bye = new ThankYou(); public static ThankYou Bye { get { return bye; } } } 

现在你可以使用Func<..., ThankYou>而不是Action<...>

 public ThankYou MethodWithNoResult() { /* do things */ return ThankYou.Bye; } 

或者使用Rx团队已经完成的工作: http : //msdn.microsoft.com/en-us/library/system.reactive.unit%28v=VS.103%29.aspx

您可以简单地使用Object如其他人所build议的。 或者我已经看到一些使用Int32 。 使用Int32引入了一个“虚拟”数字(使用0 ),但至less不能将任何大的和奇特的对象放入Int32引用(结构被封闭)。

你也可以写你自己的“空白”types:

 public sealed class MyVoid { MyVoid() { throw new InvalidOperationException("Don't instantiate MyVoid."); } } 

MyVoid引用是允许的(它不是一个静态类),但只能是null 。 实例构造函数是私有的(如果有人试图通过reflection来调用这个私有构造函数,将抛出exception)。

void虽然是一个types,但仅作为方法的返回types有效。

void这种限制void

我喜欢上面的Aleksey Bykov的想法,但可以简化一下

 public sealed class Nothing { public static Nothing AtAll { get { return null; } } } 

正如我看到没有明显的原因,为什么Nothing.AtAll不能只给零

同样的想法(或Jeppe Stig Nielsen的观点)也适用于input类。

例如,如果该types仅用于描述作为某个方法的parameter passing的过程/函数的参数,并且它本身不包含任何参数。

(你仍然需要制作一个虚拟包装器或允许一个可选的“Nothing”,但是恕我直言,类的使用看起来不错,myClass <Nothing>)

 void myProcWithNoArguments(Nothing Dummy){ myProcWithNoArguments(){ } 

要么

 void myProcWithNoArguments(Nothing Dummy=null){ ... }