C#泛型中的void?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11318973/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
void in C# generics?
提问by directedition
I have a generic method that takes a request and provides a response.
我有一个接受请求并提供响应的通用方法。
public Tres DoSomething<Tres, Treq>(Tres response, Treq request)
{/*stuff*/}
But I don't always want a response for my request, and I don't always want to feed request data to get a response. I also don't want to have to copy and paste methods in their entirety to make minor changes. What I want, is to be able to do this:
但是我并不总是想要对我的请求做出响应,并且我并不总是想要提供请求数据来获得响应。我也不想为了做微小的改变而完全复制和粘贴方法。我想要的是能够做到这一点:
public Tre DoSomething<Tres>(Tres response)
{
return DoSomething<Tres, void>(response, null);
}
Is this feasible in some manner? It seems that specifically using void doesn't work, but I'm hoping to find something analogous.
这以某种方式可行吗?似乎专门使用 void 不起作用,但我希望找到类似的东西。
采纳答案by dasblinkenlight
You cannot use void, but you can use object: it is a little inconvenience because your would-be-voidfunctions need to return null, but if it unifies your code, it should be a small price to pay.
你不能用void,但你可以用object:这有点不方便,因为你的潜在void函数需要返回null,但如果它统一了你的代码,那应该是一个很小的代价。
This inability to use voidas a return type is at least partially responsible for a split between the Func<...>and Action<...>families of generic delegates: had it been possible to return void, all Action<X,Y,Z>would become simply Func<X,Y,Z,void>. Unfortunately, this is not possible.
这种无法void用作返回类型的原因至少部分是造成泛型委托Func<...>和Action<...>泛型委托家族之间的分裂的原因:如果可以返回void,那么一切Action<X,Y,Z>都会变得简单Func<X,Y,Z,void>。不幸的是,这是不可能的。
回答by Oded
void, though a type, is only valid as a return type of a method.
void,虽然是一种类型,但仅作为方法的返回类型有效。
There is no way around this limitation of void.
没有办法绕过void.
回答by Jon Skeet
No, unfortunately not. If voidwere a "real" type (like unitin F#, for example) life would be a lot simpler in many ways. In particular, we wouldn't need both the Func<T>and Action<T>families - there'd just be Func<void>instead of Action, Func<T, void>instead of Action<T>etc.
不,不幸的是没有。如果void是“真实”类型(例如unit在 F# 中),生活在很多方面都会简单得多。特别是,我们不需要 theFunc<T>和Action<T>familys - 只需要Func<void>而不是Action,Func<T, void>而不是Action<T>等。
It would also make async simpler - there'd be no need for the non-generic Tasktype at all - we'd just have Task<void>.
它也会使异步更简单——根本不需要非泛型Task类型——我们只需要Task<void>.
Unfortunately, that's not the way the C# or .NET type systems work...
不幸的是,这不是 C# 或 .NET 类型系统的工作方式......
回答by Jeppe Stig Nielsen
You could simply use Objectas others have suggested. Or Int32which I have seen some use. Using Int32introduces a "dummy" number (use 0), but at least you can't put any big and exotic object into an Int32reference (structs are sealed).
您可以简单地Object按照其他人的建议使用。或者Int32我已经看到了一些用途。UsingInt32引入了一个“虚拟”数字(use 0),但至少您不能将任何大而奇特的对象放入Int32引用中(结构是密封的)。
You could also write you own "void" type:
您也可以编写自己的“void”类型:
public sealed class MyVoid
{
MyVoid()
{
throw new InvalidOperationException("Don't instantiate MyVoid.");
}
}
MyVoidreferences are allowed (it's not a static class) but can only be null. The instance constructor is private (and if someone tries to call this private constructor through reflection, an exception will be thrown at them).
MyVoid允许引用(它不是静态类)但只能是null. 实例构造函数是私有的(如果有人试图通过反射调用这个私有构造函数,则会向他们抛出异常)。
Since value tuples were introduced (2017, .NET 4.7), it is maybe natural to use the struct ValueTuple(the 0-tuple, the non-generic variant) instead of such a MyVoid. Its instance has a ToString()that returns "()", so it looks like a zero-tuple. As of the current version of C#, you cannot use the tokens ()in code to get an instance. You can use default(ValueTuple)or just default(when the type can be inferred from the context) instead.
由于引入了值元组(2017 年,.NET 4.7),使用结构体ValueTuple(0 元组,非通用变体)而不是这样的MyVoid. 它的实例有一个ToString()返回"()",所以它看起来像一个零元组。从 C# 的当前版本开始,您不能()在代码中使用令牌来获取实例。您可以使用default(ValueTuple)or just default(当可以从上下文中推断出类型时)。
回答by Trident D'Gao
Here is what you can do. As @JohnSkeet said there is no unit type in C#, so make it yourself!
这是你可以做的。正如@JohnSkeet 所说,C# 中没有单位类型,所以自己做吧!
public sealed class ThankYou {
private ThankYou() { }
private readonly static ThankYou bye = new ThankYou();
public static ThankYou Bye { get { return bye; } }
}
Now you can always use Func<..., ThankYou>instead of Action<...>
现在您可以随时使用Func<..., ThankYou>代替Action<...>
public ThankYou MethodWithNoResult() {
/* do things */
return ThankYou.Bye;
}
Or use something already made by the Rx team: http://msdn.microsoft.com/en-us/library/system.reactive.unit%28v=VS.103%29.aspx
或者使用 Rx 团队已经制作的东西:http: //msdn.microsoft.com/en-us/library/system.reactive.unit%28v=VS.103%29.aspx
回答by Eske Rahn
I like the idea by Aleksey Bykov above, but it could be simplified a bit
我喜欢上面 Aleksey Bykov 的想法,但可以稍微简化一下
public sealed class Nothing {
public static Nothing AtAll { get { return null; } }
}
As I see no apparent reason why Nothing.AtAll could not just give null
因为我看不出为什么 Nothing.AtAll 不能给出 null
The same idea (or the one by Jeppe Stig Nielsen) is also great for usage with typed classes.
同样的想法(或 Jeppe Stig Nielsen 的想法)也适用于类型化类。
E.g. if the type is only used to describe the arguments to a procedure/function passed as an argument to some method, and it itself does not take any arguments.
例如,如果该类型仅用于描述作为参数传递给某个方法的过程/函数的参数,并且它本身不接受任何参数。
(You will still need to either make a dummy wrapper or to allow an optional "Nothing". But IMHO the class usage looks nice with myClass<Nothing> )
(您仍然需要制作一个虚拟包装器或允许可选的“Nothing”。但恕我直言,类使用 myClass<Nothing> 看起来不错)
void myProcWithNoArguments(Nothing Dummy){
myProcWithNoArguments(){
}
or
或者
void myProcWithNoArguments(Nothing Dummy=null){
...
}
回答by Gru
What I currently do is create custom sealed types with private constructor. This is better than throwing exceptions in the c-tor because you don't have to get until runtime to figure out the situation is incorrect. It is subtly better than returning a static instance because you don't have to allocate even once. It is subtly better than returning static null because it is less verbose on the call side. The only thing the caller can do is give null.
我目前所做的是使用私有构造函数创建自定义密封类型。这比在 c-tor 中抛出异常要好,因为您不必等到运行时才能确定情况不正确。它比返回静态实例要好得多,因为您甚至不必分配一次。它比返回静态 null 稍微好一点,因为它在调用端不那么冗长。调用者唯一能做的就是给出 null。
public sealed class Void {
private Void() { }
}
public sealed class None {
private None() { }
}

