void in C# generics?

C#Generics

C# Problem Overview


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.

C# Solutions


Solution 1 - C#

You cannot use void, but you can use object: it is a little inconvenience because your would-be-void functions need to return null, but if it unifies your code, it should be a small price to pay.

This inability to use void as 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.

Solution 2 - C#

No, unfortunately not. If void were a "real" type (like unit in 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.

It would also make async simpler - there'd be no need for the non-generic Task type at all - we'd just have Task<void>.

Unfortunately, that's not the way the C# or .NET type systems work...

Solution 3 - C#

Here is what you can do. As @JohnSkeet said there is no unit type in C#, so make it yourself!

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<...>

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

Solution 4 - C#

You could simply use Object as others have suggested. Or Int32 which I have seen some use. Using Int32 introduces a "dummy" number (use 0), but at least you can't put any big and exotic object into an Int32 reference (structs are sealed).

You could also write you own "void" type:

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

MyVoid references 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).


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.

Solution 5 - C#

I like the idea by Aleksey Bykov above, but it could be simplified a bit

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

The same idea (or the one by Jeppe Stig Nielsen) is also great for usage with typed classes.

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> )

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

or

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

Solution 6 - C#

void, though a type, is only valid as a return type of a method.

There is no way around this limitation of void.

Solution 7 - C#

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.

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

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiondirecteditionView Question on Stackoverflow
Solution 1 - C#Sergey KalinichenkoView Answer on Stackoverflow
Solution 2 - C#Jon SkeetView Answer on Stackoverflow
Solution 3 - C#Trident D'GaoView Answer on Stackoverflow
Solution 4 - C#Jeppe Stig NielsenView Answer on Stackoverflow
Solution 5 - C#Eske RahnView Answer on Stackoverflow
Solution 6 - C#OdedView Answer on Stackoverflow
Solution 7 - C#GruView Answer on Stackoverflow