2012-07-03 14 views
60

私は要求を受けて応答を提供する一般的な方法を持っています。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を使用しても機能しないようですが、私は類似のものを見つけることを望んでいます。

+1

System.Objectを使用して、DoSomething(Tresレスポンス、Treqリクエスト)でヌルチェックをしないのはなぜですか? – James

+0

戻り値を使用する必要があることに注意してください。手続きのような関数を呼び出すことができます。 –

答えて

61

あなたがvoidを使用することはできませんが、objectを使用することができます:あなたのだろう-BE- void機能がnullを返却する必要があるので、それは少し不便ですが、それはあなたのコードを統合した場合、支払うために小さな価格でなければなりません。

戻り値の型としてvoidを使用するには、このできないことは、一般的な代表団のFunc<...>Action<...>家族間の分割のために少なくとも部分的に責任がある:それはvoidを戻すことが可能であった、すべてのAction<X,Y,Z>は単にFunc<X,Y,Z,void>なります。残念ながら、これは不可能です。

+26

**(Joke)**そして、彼は 'return System.Runtime 'を使って、voidメソッドである' void'を返すことができます。 Serialization.FormatterServices.GetUninitializedObject(typeof(void)); '。しかし、箱入りのボイドになります。 –

1

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

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

61

いいえ、残念ながらありません。 voidが「本当の」タイプ(たとえばunit in F#など)だった場合、人生は多くの点でずっと簡単になります。特に、我々は両方のFunc<T>Action<T>家族を必要としない - は必要ないだろう - ちょうどそれはまた、より単純な非同期(async)になるだろう代わりにAction<T>など

Func<void>代わりのActionFunc<T, void>があると思います非一般的なTaskタイプです。私たちはちょうどTask<void>です。

残念ながら、それはC#や.NETの型システムの働き方ではありません...

+4

'残念なことに、これはC#または.NETのシステムが動作する方法ではありません。「最終的にはうまくいくかもしれないと私は期待していました。あなたの最後のポイントは、私たちがこれまでにそうした方法で仕事をする可能性はないということですか? –

+2

@Sahuagin:私はそう思わない - これはかなり大きな変更になるだろう。 –

+0

voidを型として許可すると、nullを参照として許可するようになりますか? もう10億ドルの間違い? – stannius

13

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

また、あなたは「無効」タイプを所有して書くことができます:

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

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

+2

これには別の名前がヌルオブジェクトパターン(デザインパターン)になります。 – Aelphaeis

18

あなたのできることは次のとおりです。 @ 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

+0

System.Reactive.Unitは良い提案です。 2016年11月現在、Unitクラス以外のものを使用していないため、Reactiveフレームワークを可能な限り小さくすることに興味がある場合は、nugetパッケージマネージャ 'Install-Package System.Reactive.Core' – DannyMeister

1

私は上記のアレクセイ・Bykovでアイデアを好きですが、それができました少し簡略化する

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

私なぜなら、Nothing.AtAllがヌルを返すだけではない理由はありません。

同じ考え方(またはJeppe Stig Nielsenによるもの)は、型付きクラスでの使用にも適しています。

など。その型が、あるメソッドの引数として渡されるプロシージャ/関数への引数を記述するためにのみ使用され、それ自体は引数をとらない場合。

(あなたはまだダミーラッパーを作成するか、またはオプション「何を」許可しないする必要があります。しかし、クラスの使用法は、MyClassの<ナッシング>と良さそうに見えます私見)

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

または

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

を使用してください値 'null'は、欠落しているか存在しない'オブジェクト 'を意味します。 'Nothing'の値が1つだけであれば、他の何もののように見えることはありません。 – LexieHankins