Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#泛型中的void?_C#_Generics - Fatal编程技术网

C#泛型中的void?

C#泛型中的void?,c#,generics,C#,Generics,我有一个接受请求并提供响应的通用方法 public Tres DoSomething<Tres, Treq>(Tres response, Treq request) {/*stuff*/} 公共Tres剂量测量(Tres响应、Treq请求) {/*东西*/} 但我并不总是希望请求得到响应,也不总是希望通过提供请求数据来获得响应。我也不想为了做一些小的改变而不得不复制和粘贴整个方法。我想要的是能够做到这一点: public Tre DoSomething<Tres>(

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

public Tres DoSomething<Tres, Treq>(Tres response, Treq request)
{/*stuff*/}
公共Tres剂量测量(Tres响应、Treq请求)
{/*东西*/}
但我并不总是希望请求得到响应,也不总是希望通过提供请求数据来获得响应。我也不想为了做一些小的改变而不得不复制和粘贴整个方法。我想要的是能够做到这一点:

public Tre DoSomething<Tres>(Tres response)
{
    return DoSomething<Tres, void>(response, null);
}
公共Tre剂量测量(Tre响应)
{
返回剂量测量(响应,空);
}

这在某种程度上可行吗?具体使用void似乎不起作用,但我希望找到类似的方法。

void
,虽然是一种类型,但仅作为方法的返回类型有效


没有办法绕过
void

的这个限制,你不能使用
void
,但是你可以使用
object
:这是一个小小的不便,因为你想要的
void
函数需要返回
null
,但是如果它统一了你的代码,那么付出的代价应该很小


无法将
void
用作返回类型,这至少部分导致了
Func
Action
泛型委托族之间的分裂:如果能够返回
void
,所有
Action
都将变成
Func
。不幸的是,这是不可能的。

不,不幸的是不可能。如果
void
是一种“真正的”类型(比如说),生活在很多方面都会简单得多。特别是,我们不需要同时使用
Func
Action
系列-只需要
Func
而不是
Action
Func
而不是
Action

它还将使异步更简单-根本不需要非泛型的
任务
类型-我们只需要
任务


不幸的是,这不是C#或.NET类型系统的工作方式…

您可以像其他人建议的那样简单地使用
对象。或者
Int32
,我已经看到了它的一些用途。使用
Int32
引入了一个“虚拟”数字(使用
0
),但至少不能将任何大的外来对象放入
Int32
引用中(结构是密封的)

您也可以编写自己的“void”类型:

MyVoid
允许引用(它不是静态类),但只能是
null
。实例构造函数是私有的(如果有人试图通过反射调用这个私有构造函数,就会向他们抛出异常)



由于引入了值元组(2017,.NET 4.7),使用(0元组,非泛型变量)而不是这样的
MyVoid
可能是很自然的。它的实例有一个返回
“()”
ToString()
,因此它看起来像一个零元组。从当前版本的C#开始,您不能使用代码中的标记
()
来获取实例。您可以使用
default(ValueTuple)
或仅使用
default
(当可以从上下文推断类型时)。

以下是您可以执行的操作。正如@JohnSkeet所说的,C#中没有单位类型,所以自己制作吧

public sealed class ThankYou {
   private ThankYou() { }
   private readonly static ThankYou bye = new ThankYou();
   public static ThankYou Bye { get { return bye; } }
}
现在,您可以始终使用
Func
而不是
Action


或者使用Rx团队已经制作的东西:

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

public sealed class Nothing {
    public static Nothing AtAll { get { return null; } }
}
因为我看不出任何明显的原因,Nothing.AtAll不能给出null

同样的想法(或者Jeppe Stig Nielsen的想法)也适用于类型化类

例如,如果类型仅用于描述作为参数传递给某个方法的过程/函数的参数,而它本身不接受任何参数

(您仍然需要创建一个虚拟包装器,或者允许一个可选的“Nothing”(无)。但是,在myClass中,类的使用看起来很好)


我现在做的是用私有构造函数创建自定义的密封类型。这比在c-tor中抛出异常要好,因为您不必等到运行时才能发现情况不正确。这比返回静态实例要好得多,因为您甚至不必分配一次。它比返回静态null要好得多,因为它在调用端不太冗长。调用者唯一能做的就是给null

public sealed class Void {
    private Void() { }
}

public sealed class None {
    private None() { }
}

为什么不直接使用System.Object并在DoSomething(Tres响应、Treq请求)中执行空检查?请注意,您确实需要使用返回值。您可以调用过程之类的函数<代码>剂量测定法(x)而不是
y=剂量(x)
我想你是想说,“注意,你不需要使用返回值。”@OlivierJacot Descombes
不幸的是,这不是C#或.NET类型系统的工作方式…
你让我对事情最终可能会像那样工作抱有希望。你的最后一点是不是意味着我们不可能让事情以这种方式运行?@Sahuagin:我怀疑不是-在这一点上,这将是一个相当大的变化。@stannius:不,我认为这比导致错误代码的事情更麻烦。单位引用类型比空值类型更能代表“void”吗?空值类型似乎更适合我,它不带值,也不占用空间。我想知道为什么void没有像这样实现。从堆栈中弹出或不弹出它不会有任何区别(在IL中,谈论本机代码可能会有所不同)。@Ondrej:我以前尝试过使用空结构,但在CLR中它最终不是空的。。。当然,这可能是特殊情况。除此之外,我不知道我会建议哪一个;我没怎么想过。它的另一个名字是空对象模式(设计模式)。@Aelphaeis这个概念与空对象模式有点不同。这里,重点是要有一些类型,我们可以与泛型一起使用。空对象模式的目标是避免编写
public sealed class Nothing {
    public static Nothing AtAll { get { return null; } }
}
void myProcWithNoArguments(Nothing Dummy){
     myProcWithNoArguments(){
}
void myProcWithNoArguments(Nothing Dummy=null){
    ...
}
public sealed class Void {
    private Void() { }
}

public sealed class None {
    private None() { }
}