1

I always thought that anonymous functions are as mighty as named functions until I wanted to turn a private named function into a anonymous function because just one method body need to call this function. A trivial example:

public void Init(List<int> numbers, List<string> texts)
{
  int n = GetFirst(numbers);
  string t = GetFirst(texts);
}

private T GetFirst<T>(List<T> list)
{
  return list[0];
}

Desired would be to define something like

GenFunc<T, List<T>, T> getFirst = list => list[0];

and use that instead of the instance method GetFirst. Using Func is not possible because the generic parameters have a different semantic. I therefore defined a delegate (the "base" of Func)

delegate T GetFirstDelegate<T>(List<T> list);

but I can instantiate it only with defined generic parameters e.g.

GetFirstDelegate<string> getFirst = list => list[0];

but not as I wish to with placeholder generic parameters:

GetFirstDelegate<T> getFirst = list => list[0];

This makes me think that anonymous methods are not as mightly as named methods - at least in terms of generic usage - or am I missing something?

David
  • 2,426
  • 3
  • 24
  • 36

3 Answers3

2

Looking at this question, you can see that generic anonymous functions are not possible in C#. Imaging when the compiler has to do with a regular generic method. It actually generates an overload for each type it was called for (simplisticly at least). When you declare a variable with a generic parameter, how should the compiler do in this instance? It can't generate new variables with different generic parameters.

Hope this is clear. You basicly just have to know that generic methods and classes are a compile-time thing!

Community
  • 1
  • 1
Philippe Paré
  • 4,279
  • 5
  • 36
  • 56
1

What you are actually trying to do is to create a generic variable like that

Func<List<T>, T> getFirst<T> = list => list[0];

But unfortunatly this is not valid C# as variables cannot be generic. Only types (interfaces, classes, structs), delegates and methods can be generic.

René Vogt
  • 43,056
  • 14
  • 77
  • 99
0

The signature for a function that accepts List<T> as input and return T is Func<List<T>, T> and not Func<T, List<T>, T>.

I think this is what you wanted :

private Func<List<T>, T> GenGetFirst<T>()
{
    return list => list[0];
}

Usage:

public void Init(List<int> numbers, List<string> texts)
{
    int n = GenGetFirst<int>()(numbers);
    string t = GenGetFirst<string>()(texts); 
}

Or in a more clear way:

public void Init(List<int> numbers, List<string> texts)
{
    Func<List<int>, int> intFunc = GenGetFirst<int>();
    Func<List<string>, string> stringFunc = GenGetFirst<string>();

    int n = intFunc(numbers);
    string t = stringFunc(texts);
}
Zein Makki
  • 29,485
  • 6
  • 52
  • 63
  • I appreciate your answer, but I wanted to get rid of the named method and express it with an anonymous function which is not possible in C# like I just learned. – David Jul 06 '16 at 12:56