C# Type inference change for Orcas


While playing around with a batch of Orcas code recently I found a welcome change to the C# type inference rules for Orcas.  The return type of a generic delegate can now be inferred from the actual return values.  Here is some sample code demonstrating the problem. 

    class Program
    {
        public delegate T Operation<T>();

        public static void M<T>(Operation<T> del)
        {

        }

        static void Main(string[] args)
        {
            M(delegate { return 42; });
        }
    }

In Whidbey the above code will fail with a compiler error.

error CS0411: The type arguments for method ‘ConsoleApplication34.Program.M<T>(ConsoleApplication34.Program.Operation<T>)’ cannot be inferred from the usage. Try specifying the type arguments explicitly.

This is really frustrating in Whidbey because the you have to modify the call to include the actual type specifier. 

            M<int>(delegate { return 42; });

However this code now works without modification in Orcas.  This is a welcome and extremely useful change. 

And yes, the same inference is possible with VB in Orcas.  In Whidbey this was not an issue because VB did not support lambda expressions. 

Module Module1

    Public Delegate Function Operation(Of T)() As T

    Public Sub M(Of T)(ByVal del As Operation(Of T))

    End Sub

    Sub Main()
        M(Function() 1)
    End Sub

End Module
Comments (5)

  1. Michael says:

    It’s a good start, but they need to take type inference all the way…

  2. jaredpar says:

    Where are some other areas you’d like to see it go?

  3. grauenwolf says:

    Constructors on generics would be nice.

  4. jaredpar says:

    Completely agree on a better way for type intference on generic constructors.  There is a work around that gives you the inference with little design overhead.  

    class C1<T>

    {

      C1(T val)

      {… }

    }

    class C1

    {

      public static C1<T> Create<T>(T val)

      {

         return new C1<T>(1);

      }

    }

    class Program

    {

      public static void Main()

      {

        var c = C1.Create(5);

      }

    }

  5. Michael says:

    Quick list off the top of my head:

    Inference from method groups

    Inference from return methods (i.e., int main() {return foo();} // where foo is Foo<T>)

    Automatic conversion from method group to Func (I guess this means type equivalency for all delegates that share a signature).

    var keyword outside of locals (fields for example)

    Nice syntax to declare a Func / disambiguate against Expression<T>

    Wildcard for specifying type parameters. For instance: Func<int,*> int2string = a => a.ToString(); // I need to specify the type for A, but the return type can be infered. Same for calling methods:

    Foo<*,string>(someLocal); // * can be inferred from someLocal type.

    Implementing these small things would go a long way to making C# look and work much nicer…