In C#, how to instantiate a passed generic type inside a method?

前端 未结 8 1019
逝去的感伤
逝去的感伤 2020-11-30 21:19

How can I instantiate the type T inside my InstantiateType method below?

I\'m getting the error: \'T\' is a \'type parameter\' but is u

相关标签:
8条回答
  • 2020-11-30 21:25

    To extend on the answers above, adding where T:new() constraint to a generic method will require T to have a public, parameterless constructor.

    If you want to avoid that - and in a factory pattern you sometimes force the others to go through your factory method and not directly through the constructor - then the alternative is to use reflection (Activator.CreateInstance...) and keep the default constructor private. But this comes with a performance penalty, of course.

    0 讨论(0)
  • 2020-11-30 21:26

    You can also use reflection to fetch the object's constructor and instantiate that way:

    var c = typeof(T).GetConstructor();
    T t = (T)c.Invoke();
    
    0 讨论(0)
  • 2020-11-30 21:29

    Using a factory class to build your object with compiled lamba expression: The fastest way I've found to instantiate generic type.

    public static class FactoryContructor<T>
    {
        private static readonly Func<T> New =
            Expression.Lambda<Func<T>>(Expression.New(typeof (T))).Compile();
    
        public static T Create()
        {
            return New();
        }
    }
    

    Here is the steps I followed to set up the benchmark.

    Create my benchmark test method:

    static void Benchmark(Action action, int iterationCount, string text)
    {
        GC.Collect();
        var sw = new Stopwatch();
        action(); // Execute once before
    
        sw.Start();
        for (var i = 0; i <= iterationCount; i++)
        {
            action();
        }
    
        sw.Stop();
        System.Console.WriteLine(text + ", Elapsed: {0}ms", sw.ElapsedMilliseconds);
    }
    

    I've also tried using a factory method:

    public static T FactoryMethod<T>() where T : new()
    {
        return new T();
    }
    

    For the tests I've created the simplest class :

    public class A { }
    

    The script to test:

    const int iterations = 1000000;
    Benchmark(() => new A(), iterations, "new A()");
    Benchmark(() => FactoryMethod<A>(), iterations, "FactoryMethod<A>()");
    Benchmark(() => FactoryClass<A>.Create(), iterations, "FactoryClass<A>.Create()");
    Benchmark(() => Activator.CreateInstance<A>(), iterations, "Activator.CreateInstance<A>()");
    Benchmark(() => Activator.CreateInstance(typeof (A)), iterations, "Activator.CreateInstance(typeof (A))");
    

    Results over 1 000 000 iterations:

    new A(): 11ms

    FactoryMethod A(): 275ms

    FactoryClass A .Create(): 56ms

    Activator.CreateInstance A (): 235ms

    Activator.CreateInstance(typeof (A)): 157ms

    Remarks: I've tested using both .NET Framework 4.5 and 4.6 (equivalent results).

    0 讨论(0)
  • 2020-11-30 21:32

    Declare your method like this:

    public string InstantiateType<T>(string firstName, string lastName) 
                  where T : IPerson, new()
    

    Notice the additional constraint at the end. Then create a new instance in the method body:

    T obj = new T();    
    
    0 讨论(0)
  • 2020-11-30 21:34

    Instead of creating a function to Instantiate the type

    public T InstantiateType<T>(string firstName, string lastName) where T : IPerson, new()
        {
            T obj = new T();
            obj.FirstName = firstName;
            obj.LastName = lastName;
            return obj;
        }
    

    you could have done it like this

    T obj = new T { FirstName = firstName, LastName = lastname };
    
    0 讨论(0)
  • 2020-11-30 21:36

    you want new T(), but you'll also need to add , new() to the where spec for the factory method

    0 讨论(0)
提交回复
热议问题