114

リクエストを受け取り、レスポンスを提供するジェネリックメソッドがあります。

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

ただし、リクエストに対する応答が常に必要であるとは限りません。また、応答を取得するためにリクエストデータを常にフィードする必要もありません。また、小さな変更を加えるためにメソッド全体をコピーして貼り付ける必要はありません。私が欲しいのは、これを実行できるようにすることです。

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

これは何らかの方法で実行可能ですか?特にvoidを使用しても機能しないようですが、類似したものを見つけたいと思っています。

4

7 に答える 7

115

を使用することはできませんがvoid、使用することはできます。関数を返す必要があるobjectため、少し不便ですが、コードを統合する場合は、少額の支払いが必要になります。voidnull

このリターンタイプとして使用できないことは、ジェネリックデリゲートのとファミリーのvoid間の分割の少なくとも一部の原因です。リターンが可能であった場合、すべてが単純になります。残念ながら、これは不可能です。Func<...>Action<...>voidAction<X,Y,Z>Func<X,Y,Z,void>

于 2012-07-03T20:53:40.147 に答える
93

残念ながら、そうではありません。void「実際の」タイプ(たとえばunit、F#など)の場合、人生は多くの点ではるかに単純になります。特に、Func<T>Action<T>ファミリの両方は必要ありません。の代わりに、などのFunc<void>代わりに存在するだけです。ActionFunc<T, void>Action<T>

また、非同期がより簡単になります-非ジェネリックTask型はまったく必要ありません-私たちが持っているだけTask<void>です。

残念ながら、それはC#または.NET型システムが機能する方法ではありません...

于 2012-07-03T20:54:55.420 に答える
29

これがあなたにできることです。@JohnSkeetが言ったように、C#にはユニットタイプがないので、自分で作成してください。

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

于 2013-09-26T17:15:25.387 に答える
17

Object他の人が示唆しているように、あなたは単に使うことができます。またはInt32私がいくつかの使用を見てきました。を使用Int32すると、「ダミー」の数値(use 0)が導入されますが、少なくとも、大きくてエキゾチックなオブジェクトをInt32参照に入れることはできません(構造体は封印されています)。

独自の「void」タイプを作成することもできます。

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

MyVoid参照は許可されます(静的クラスではありません)が、許可されるのは。のみですnull。インスタンスコンストラクターはプライベートです(そして、誰かがリフレクションを通じてこのプライベートコンストラクターを呼び出そうとすると、例外がスローされます)。


値タプルが導入されたため(2017、.NET 4.7)、そのような.の代わりに構造体ValueTuple(0タプル、非ジェネリックバリアント)を使用するのが自然かもしれませんMyVoid。そのインスタンスにはToString()を返すが"()"あり、ゼロタプルのように見えます。現在のバージョンのC#では()、コード内のトークンを使用してインスタンスを取得することはできません。default(ValueTuple)代わりに、または単にdefault(タイプがコンテキストから推測できる場合)を使用できます。

于 2012-07-03T21:19:58.720 に答える
8

上記のAlekseyBykovのアイデアは気に入っていますが、少し簡略化できます。

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

Nothing.AtAllが単にnullを与えることができなかった明確な理由がわからないので

同じアイデア(またはJeppe Stig Nielsenによるアイデア)は、型クラスでの使用にも最適です。

たとえば、型が何らかのメソッドへの引数として渡されたプロシージャ/関数への引数を記述するためにのみ使用され、それ自体は引数を取りません。

(ダミーのラッパーを作成するか、オプションの「Nothing」を許可する必要があります。ただし、クラスの使用法はmyClass <Nothing>で見栄えがします)

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

また

void myProcWithNoArguments(Nothing Dummy=null){
    ...
}
于 2015-06-15T19:42:21.470 に答える
4

voidは型ですが、メソッドの戻り型としてのみ有効です。

のこの制限を回避する方法はありませんvoid

于 2012-07-03T20:52:14.987 に答える
1

私が現在行っているのは、プライベートコンストラクターを使用してカスタムの封印された型を作成することです。これは、c-torで例外をスローするよりも優れています。これは、実行時まで状況が正しくないことを把握する必要がないためです。一度も割り当てる必要がないため、静的インスタンスを返すよりも微妙に優れています。呼び出し側の冗長性が少ないため、静的nullを返すよりも微妙に優れています。呼び出し元が実行できる唯一のことは、nullを与えることです。

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

public sealed class None {
    private None() { }
}
于 2019-11-12T11:51:44.073 に答える