C# 2.0 doesn't allow me to use System.Void?

I love generics in 2.0! What a time-saving feature, less code to write! Plus it allows for more code re-use, and thus fewer bugs. I love generics, pat on the back to Anders and the C# team.

I ran into a limitation, however, with C# 2 compiler and generics. I wanted to implement a method that would have a generic return type, for instance:


TReturn ExecuteSomeDelegate<TReturn>(MyReturnableDelegate<TReturn> serverMethodToExecute)
{
    // pretend there's lots of error catching & handling here...
    return serverMethodToExecute();
}

 


This is all fine and dandy:


// call some server method that returns an integer
int serverNumber = ExecuteSomeDelegate<int>(ServerReturnsIntFunction);

// call some server method that returns a string
string serverName = ExecuteSomeDelegate<string>(ServerMethodThatReturnsString);

 


However, I wanted to reuse this ExecuteSomeDelegate method to call a method that has a void return type:


// call some server method that returns void
ExecuteSomeDelegate<System.Void>(ServerMethodThatReturnsVoid); // ERROR!

 


I must say, I was surprised to see that the C# compiler issues an error message for this particular case, saying that System.Void isn't accessible in C#. What ! Why

Can anyone explain the limitation here As a workaround, I have to implement a different ExecuteSomeDelegate method that returns void, complete with duplicate error catching code found in the original method. Why the limitation, can anyone explain this


Answer this question

C# 2.0 doesn't allow me to use System.Void?

  • chrisofeaton

    Forgive my ignorance, but wasn't System.Void allowed in C# 1.x

    In any case, if the compiler is just unhappy about me calling



    void MyFunc()
    {
        return DoSomething(); // where DoSomething returns void
    }

     


    Then why not just have the compiler emit a function that doesn't explicitly do a return Why not turn this method, generic or not, into


    void MyFunc()
    {
         DoSomething();
    }

     


    It would be a minor compiler modification, to say the least, and the benefit would be that I could reuse a generic method for all generic type instanciations:


    // MyFunc called with a System.Int32 type specifier
    void MyFunc<int>()
    {
         return DoSomething();
    }

    // MyFunc called with a System.Void type specifier
    void MyFunc<Void>()
    {
         DoSomething();
    }

     


    This is frustrating; in my real-world code, I have duplicate code bases for these functions: a generic MyFunc that returns some value, and a MyFunc that returns void, both with identical error catching blocks and handling code. Real pain!



  • panzin

    I did not know that Managed C++ treated those two declarations as equivallent - you learn something new every day :) Even though I do work at Microsoft, I don't work on the CLR team (as you may have noticed)

    I agree that you could have defined the C# language so that returning System.Void would be the same as returning void. This is still a compiler level special handling of the System.Void return type though; if there wasn't I'd imagine that the compiler would have generated:


    .method public static [mscorlib]System.Void modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl)
            foo() cil managed
    {
      .vtentry 2 : 1
     
    // Code size       1 (0x1)
      .maxstack  0
      IL_0000:  ret
    } // end of method 'Global Functions'::foo


     


    instead of:


    .method public static void modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl)
            foo() cil managed
    {
      .vtentry 2 : 1
     
    // Code size       1 (0x1)
      .maxstack  0
      IL_0000:  ret
    } // end of method 'Global Functions'::foo


     


    I personally don't see a huge benefit of one over the other interpretation of how to handle System.Void return value declarations, but it is always interesting to see how you can solve the same problem in different ways.

    Best regards,
    Johan Stenberg


  • AbhiM

    Can someone knowledgable tell me if there is a .NET technical limitation on using System.Void as a type argument for a generic method, i.e. SomeMethod<System.Void>()

    Can anyone answer this



  • John Joslin

    Isn't the technical limitation in essence that if you specify a function with a void return type, the compiler doesn't expect a return expression
    Without the generics it comes down to this

    void Test1()
    {
       return test2(); <- This gives an error:Error 1 Since 'Test1()'
                          returns void, a return keyword must not be
                          followed by an object expression 

    }

    void test2()
    {
        ...
    }


  • Manivakkam Krishnan

    "System.Void is a special type in that you can't create instances of it."

    Johan, I'm not trying to create instances of Void, but rather, I'm trying to use System.Void as a type specifier on a generic method. For instance: SomeMethod<System.Void>()

    "The compiler does not expect a return expression"

    But that's just a compiler error, telling you not to use the return keyword when a method returns void.

    Is there an actual limitation in the CLR or JIT compiler regarding this


  • DarkSkies

    I can't test it in front of me, but have you tried just 'void'. You can't use System.Void in C#, however it happily allows you to do this:


    Type voidType = typeof(void);
     


  • skinny2

     Johan Stenberg wrote:
    Again, the following method declarations are *not* semantically equivallent (and the first one is actually illegal):



    System.Void foo () {};
    void foo() { };

     
    But only in c#.  In Managed C++ the corresponding two lines are equivalent and both are legal.


    System::Void foo ()
    {
    }

    .method public static void modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl)
            foo() cil managed
    {
      .vtentry 2 : 1
      // Code size       1 (0x1)
      .maxstack  0
      IL_0000:  ret
    } // end of method 'Global Functions'::foo

    void bar()
    {
    }

    .method public static void modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl)
            bar() cil managed
    {
      .vtentry 3 : 1
      // Code size       1 (0x1)
      .maxstack  0
      IL_0000:  ret
    } // end of method 'Global Functions'::bar

     


    One wold return an instance of type System.Void, the other have no return value.
    So far as it makes sense to discuss the semantics of an invalid declaration, if C# allowed you to declare a method as returning System.Void I imagine it would be equivalent to declaring that the method had no return type just like Managed C++. 

    See the definition of System.Void
    http://msdn.microsoft.com/library/en-us/cpref/html/frlrfsystemvoidclasstopic.asp

  • ChrisA

    The CLR has special handling of the System.Void type. I would think of it as a meta-type that is mostly useful within the context of reflection.

    In your example, you are telling the compiler that you want to return an instance of type System.Void. This is different from not returning anything, and both the C# compiler and the CLR runtime will be unhappy with this.

    Best regards,
    Johan Stenberg

  • Bob Meyers MSFT

    According to the Common Language Infrastructure (CLI) working draft 2.9.1, section 9.4, System.Void is not valid as an argument in instantiations of generic types or methods. So this is not a C# specific thingie.

    You can find the working drafts on:
    http://msdn.microsoft.com/net/ecma/#Working%20Draft%202.9.1

    And as far as I know, System.Void was only allowed in the context of gettype(void) - that is, you could only use the type itself, in C#1.x. This shouldn't have changed in 2.0.

    Changing this would *not* simply be a C# compiler issue. What if you make the method public And you used this exported method from another language (i.e. J# or VB)
    What would happen in a late-bound case where you bind the parameters of the generic method/type at runtime

    Again, the following method declarations are *not* semantically equivallent (and the first one is actually illegal):



    System.Void foo () {};
    void foo() { };

     


    One wold return an instance of type System.Void, the other have no return value.

    Best regards,
    Johan Stenberg

  • wormus

     Judah wrote:
    Forgive my ignorance, but wasn't System.Void allowed in C# 1.x
    Not in the context of declaring a generic - generics weren't implemented until 2.0.

    Then why not just have the compiler emit a function that doesn't explicitly do a return
    I think you are taking the wrong tack here.  Instead of focusing on how the compiler might emit code under some circumstances think about the behaviour the programmer should expect.

    For example, the following generic class MyClass<T> has a method DoSomething that returns the same type as the generic's type parameter and a second method DoSomethingElse which calls DoSomething to manipulate the variable memberVariable. 

    If MyClass<void> were valid, what value would memberVariable have after DoSomethingElse() had been called



    public
    class MyClass<T>
    {
         public T DoSomething ()
         {
              T t =
    new T ();

              /* imagine some really useful code here */

              return t;
         }

         public T memberVariable = null;

         public int DoSomethingElse ()
         {

              memberVariable = DoSomething ();
         }
    }

     


    This is frustrating; in my real-world code, I have duplicate code bases for these functions: a generic MyFunc that returns some value, and a MyFunc that returns void
    Why do you feel the need to have two versions of MyFunc, one of which doesn't return a result   Why not have one version that returns a result and just ignore the result returned if you don't need/want it





  • Larry Aultman

    Let me see if I got this right.

    When you use a generic type, the JITter generates code specific to the type you used and executes it.

    Let's say C# allowed you to use void as a type parameter, and then you have a method signature like this:

    int Foo<T>(T bar, int count);

    Now, how would I call Foo with T=void   What would I pass in for bar   How can the Jitter generate code for this case  

    That's the reason, I believe, why voids are special cased out.

  • Idizz

    David, unfortunately it seems the C# void keyword doesn't quite work like the other C# alias keywords. Trying your suggestion:


    SomeMethod<void>(); // Error: void cannot be used in this context
     

    Vijaye, thanks for your input. Let me address some of your questions.

    "Now, how would I call Foo with T=void What would I pass in for bar "

    You couldn't, unless you've done the default constructor of System.Void (System.Void is a value type, and therefore has a public default constructor). Even if we couldn't pass System.Void as an argument, that doesn't mean we shouldn't be able to use System.Void for other things, such as return values, should it

    "How can the Jitter generate code for this case "

    It would generate the normal IL codes; again, we know that System.Void has a default public constructor, so I don't see any technical limitation on the just-in-time compilation engine for this case.

    I guess I just don't see any reasons for preventing the use of a datatype simply because it seems useless as a normal function parameter. As demonstrated before, there is a use for System.Void as a type specifier for a generic method. Unless there are some technical limitations in the CLR, I think it is a mistake to prevent the usage of a public, fundamental .NET framework datatype such as System.Void, solely on the basis of a "it makes no sense to use it as a paramter" argument.

    Can someone knowledgable tell me if there is a .NET technical limitation on using System.Void as a type argument for a generic method, i.e. SomeMethod<System.Void>()



  • Seaxouri

    System.Void is a special type in that you can't create instances of it. It's intended use is in the System.Reflection namespace to indicate that a function doesn't return a value. For more info, see:

    http://msdn.microsoft.com/library/default.asp url=/library/en-us/cpref/html/frlrfsystemvoidclasstopic.asp


    Best regards,
    Johan Stenberg



  • C# 2.0 doesn't allow me to use System.Void?