Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to store a generic function in a variable in c#? [duplicate]

I have the following code:

public interface IMenuItem
{
    IWebElement Parent { get; }
}


public class MenuItems
{
    public T GetMenuItem<T>() where T : IMenuItem, new()
    {
        var menuItem = new T();

        return menuItem;
    }
}


public abstract class Page : IEnumerable<IComponent>
{
    private Func<IMenuItem> _getMenuItems = new MenuItems().GetMenuItem<IMenuItem>;
}

I'm trying to store the new MenuItems().GetMenuItem<IMenuItem> function in _getMenuItems field, but since this is a generic function this isn't working. How can I store generic functions into a variable?

Doing new MenuItems().GetMenuItem<IMenuItem> won't work and it tells me:

'IMenuItem' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'MenuItems.GetMenuItem()'

Now I have many concrete types that implement IMenuItem I want the delegate to accept those. I don't want to make a seperate delegate for every concrete type that implements IMenuItem. Rather I have a single delegate that can accept concrete types that implement IMenuItem.

like image 306
O S Avatar asked Dec 10 '19 11:12

O S


People also ask

How do you declare a generic function?

Generic Methods All generic method declarations have a type parameter section delimited by angle brackets (< and >) that precedes the method's return type ( < E > in the next example). Each type parameter section contains one or more type parameters separated by commas.

What is generic type in C?

Generics are syntax components of a programming language that can be reused for different types of objects. Typically, generics take the form classes or functions, which take type(s) as a parameter. Generics are also commonly referred to as templates , and in C++ are officially called templates.

What is generic function give example?

You can also define generic functions that take variable numbers of arguments in just the same way as ordinary functions. For example: (defgeneric foo (a . b)) defines a generic function (with no methods) taking at least one argument, with the second always being of class <list>.


1 Answers

The problem is with the new() constraint.

The new constraint specifies that a type argument in a generic class declaration must have a public parameterless constructor. To use the new constraint, the type cannot be abstract.

Since IMenuItem is an interface, it cannot be instantiated, and therefore the new() constraint will be a problem.

Edit:

You can solve this in a couple of ways:

  1. You can use reflection for retrieving the method and invoking it:

    var method = typeof(MenuItems).GetMethod("GetMenuItem");
    var instance = new MenuItems(); // Maybe convert the class into a static class??
    var genericMethod = method.MakeGenericMethod(typeof(MenuItem1));
    var result = genericMethod.Invoke(instance, null) as IMenuItem;
    
  2. Use dynamic to invoke it:

    dynamic instance = new MenuItems(); // Maybe convert the class into a static class??
    var result = instance.GetMenuItem<MenuItem1>() as IMenuItem;
    
  3. Hold an instance of MenuItems instead of the method itself:

    var menuItems = new MenuItems();
    var result = _instance.GetMenuItem<MenuItem1>() as IMenuItem;
    
like image 167
Amir Popovich Avatar answered Oct 03 '22 22:10

Amir Popovich