Type inferrence from anonymous methods  
Author Message
Michael_Giagnocavo





PostPosted: Visual C# Language, Type inferrence from anonymous methods Top

We have a generic method to perform a common pattern on an object:

public static void UseServiceClient<T>(Action<T> action) where T : ICommunicationObject { ... }

Ideally (as far as C# 2.0 goes), the call to this method would look like:

UseServiceClient(delegate(SomeServiceClient client)
{
...
});

But this produces an error: CS0411: The type arguments for method 'UseServiceClient<T>(System.Action<T>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

So, we must call it like so:
UseServiceClient<SomeServiceClient>(delegate(SomeServiceClient client)...

Which is ugly/more verbose. If we locally declare the Action<SomeServiceClient> and pass that in, it works.

Is there any way around specifying the type twice



Visual C#5  
 
 
Figo Fei - MSFT





PostPosted: Visual C# Language, Type inferrence from anonymous methods Top

Hi, Michael

You must specify the type in <>, if you use <>.

Thank you

 



 
 
Michael_Giagnocavo





PostPosted: Visual C# Language, Type inferrence from anonymous methods Top

Yes, I know the type must be in the <>, that's why in the first example, I don't use <>. However, the compiler produces the error mentioned as it can't infer the type just from the anonymous method alone.
 
 
Figo Fei - MSFT





PostPosted: Visual C# Language, Type inferrence from anonymous methods Top

If you use <> in declaration, you have to specify the type in <T> while calling the method.

Otherwise, you'd use in this no <> way:

public delegate void MyDelegate(SomeServiceClient SSC)

public static void UseServiceClient(Mydelegate my_delegate)
{ ... }

UseServiceClient(delegate(SomeServiceClient client)
{
    ...
});

This is also anonymous delegate invoked.



 
 
Michael_Giagnocavo





PostPosted: Visual C# Language, Type inferrence from anonymous methods Top

Hello!

But that way is non-generic. This illustrates the problem better:

public static void GenericMethodA<T>(T foo) {..}

Can be called like this:
GenericMethodA(someObject); // The type T for GenericMethodA will be inferred.

However, public static void GenericMethodB<T>(Action<T> foo) {..}

Can NOT be called like this:

GenericMethodA(delegate(object x ) { ...});


Why can't the C# compiler infer the type of T for GenericMethodB


 
 
Figo Fei - MSFT





PostPosted: Visual C# Language, Type inferrence from anonymous methods Top

Hello, Michael

Commonly speaking, we suggest you specify the type when using the generic method. Because it looks more readable. When you directly use a simple type, the syntax is support (for convenience). While using delegates it is not supported (it is not simple type at all).

On the other hand, the explain can be that delegate is a special type who required other types defined as params (actually it is a pointer to methods), so it must be assigned params clearly and identically.

Thank you



 
 
Michael_Giagnocavo





PostPosted: Visual C# Language, Type inferrence from anonymous methods Top

Yes, but this works:

Action<string> foo = delegate(string x) {...}
GenericMethod(foo);

But this does not:
GenericMethod(delegate(string x) {...});

In neither case do I need to specify GenericMethod<string>, but the second case fails compiling. Here's a full example:


class Program

{

static void Main(string[] args)

{

Action<string> foo = delegate(string s) { Console.WriteLine(s); };

GenericMethod(foo);

GenericMethod(delegate(string s) { Console.WriteLine(s); });

}

static void GenericMethod<T>(Action<T> act)

{

act(default(T));

}

}

The second call produces:

C:\Projects\Temp\Program.cs(15,3): error CS0411: The type arguments for method 'Program.GenericMethod<T>(System.Action<T>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.



 
 
Figo Fei - MSFT





PostPosted: Visual C# Language, Type inferrence from anonymous methods Top

Hi, Michael

Yes, I see. Only diff is that the context diff. You must specify the type in an expression (anonymous method) such as GenericMethod<string>(delegate(string x) {...});
It's all about the context of syntax.

Thanks.