17

Specifically, I want to write this:

public Func<IList<T>, T> SelectElement = list => list.First();

But I get a syntax error at T. Can't I have a generic anonymous method?

mpen
  • 272,448
  • 266
  • 850
  • 1,236

4 Answers4

15

Nope, sorry. That would require generic fields or generic properties, which are not features that C# supports. The best you can do is make a generic method that introduces T:

public Func<IList<T>, T> SelectionMethod<T>() { return list => list.First(); }

And now you can say:

Func<IList<int>, int> selectInts = SelectionMethod<int>();
Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
6

Of course you can, but T must be known:

class Foo<T>
{
    public Func<IList<T>, T> SelectionMethod = list => list.First();
}

As an alternative you could use a generic method if you don't want to make the containing class generic:

public Func<IList<T>, T> SelectionMethod<T>()
{
    return list => list.First();
}

But still someone at compile time will need to know this T.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • Yeah..that's the problem. I don't know what T is. It could be a char or a string. – mpen Dec 02 '10 at 19:25
  • Well then hopefully the consumer (the one that instantiates it) of the `Foo` class will know it. If you never know it at compile time then generics is not the right artifact for you. – Darin Dimitrov Dec 02 '10 at 19:26
  • 2
    Well then your method or your class must take a generic parameter `T`. – cdhowie Dec 02 '10 at 19:26
  • The other problem is that I want the user to be able to override the selection method, which is why I had it as an anonymous function :) I know what `T` is when I call this method, but I use it in 2 different places (once on a List, once on a List), and I want to use the same method for both. – mpen Dec 02 '10 at 19:34
  • Well, then you could turn this `SelectionMethod` field into a virtual generic method so that the user would be able to override it. It's really a matter of method vs field here. Methods can be generic, fields can't. That's what the specification says. It's as simple as that. You can't fight against the specification or the type system. – Darin Dimitrov Dec 02 '10 at 19:36
  • By "override" I didn't mean in a subclass, I meant modify the property. – mpen Dec 02 '10 at 19:39
  • 2
    So if the user is supposed to modify this field (not property), why don't you provide him with a generic method which will take a delegate: `public void DoSomething(Func, T> foo) { ... }`. Now when the user calls this method he could pass as argument whatever expression he likes: `DoSomething(x => x.First());` and inside the method you're gonna do the job. You could even provide an overload of this method which will do the `.First()` stuff: `public void DoSomething() { ... }` and you would construct an anonymous delegate inside. – Darin Dimitrov Dec 02 '10 at 19:44
  • @Darin: I wanted to specify it at the class level for re-usability... but this is the closest solution so far. Might have to do it that way. – mpen Dec 02 '10 at 19:52
  • @Darin: Actually, that won't work either...because like I said, T takes on two different values within the function. – mpen Dec 02 '10 at 20:13
1

You declared only the return type as generic.

Try this:

public Func<IList<T>, T> SelectionMethod<T>() { return list => list.First(); }

The name of the thing you are declaring must include the type parameters for it to be a generic. The compiler supports only generic classes, and generic methods.

So, for a generic class you must have

class MyGeneric<T> { 
   // You can use T here now
   public T MyField;
 }

Or, for methods

public T MyGenericMethod<T>( /* Parameters */ ) { return T; }

You can use T as the return parameter, only if it was declared in the method name first.

Even though it looks like the return type is declared before the actual method, the compiler doesn't read it that way.

Matt Brunell
  • 10,141
  • 3
  • 34
  • 46
  • Eh? No I didn't..even before the edit. And what does that have to do with anything? – mpen Dec 02 '10 at 19:27
  • That's a better explanation. I wanted a generic lambda though, which I guess doesn't exist. – mpen Dec 02 '10 at 19:45
-1
    public static void SomeContainerFunction()
    {
        const string NULL_VALUE = (string)null;

        Type GetValueType<T>(T value) => value?.GetType() ?? typeof(T);

        var typeOfNullValue = GetValueType(NULL_VALUE);

        Debug.WriteLine($"Value: {NULL_VALUE}, Type: {typeOfNullValue}");
    }
Yuri Abele
  • 64
  • 6
  • 1
    Welcome to SO. When answering a question, please provide explanation associated with your code. Some people might not understand your code or don't see how it answers the question. See [how to write a good answer](https://stackoverflow.com/help/how-to-answer) – Nuageux Jun 02 '17 at 08:12