在C#中,如何实例化一个方法内传递的genericstypes?

我如何实例化typesT在我的InstantiateType<T>方法下面?

我得到的错误: “T”是一个“types参数”,但像一个“variables”使用。

(SCROLL DOWN FOR REFACTORED ANSWER)

 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace TestGeneric33 { class Program { static void Main(string[] args) { Container container = new Container(); Console.WriteLine(container.InstantiateType<Customer>("Jim", "Smith")); Console.WriteLine(container.InstantiateType<Employee>("Joe", "Thompson")); Console.ReadLine(); } } public class Container { public T InstantiateType<T>(string firstName, string lastName) where T : IPerson { T obj = T(); obj.FirstName(firstName); obj.LastName(lastName); return obj; } } public interface IPerson { string FirstName { get; set; } string LastName { get; set; } } public class Customer : IPerson { public string FirstName { get; set; } public string LastName { get; set; } public string Company { get; set; } } public class Employee : IPerson { public string FirstName { get; set; } public string LastName { get; set; } public int EmployeeNumber { get; set; } } } 

温和的答案:

感谢所有的评论,他们让我走上正轨,这就是我想要做的:

 using System; namespace TestGeneric33 { class Program { static void Main(string[] args) { Container container = new Container(); Customer customer1 = container.InstantiateType<Customer>("Jim", "Smith"); Employee employee1 = container.InstantiateType<Employee>("Joe", "Thompson"); Console.WriteLine(PersonDisplayer.SimpleDisplay(customer1)); Console.WriteLine(PersonDisplayer.SimpleDisplay(employee1)); Console.ReadLine(); } } public class Container { public T InstantiateType<T>(string firstName, string lastName) where T : IPerson, new() { T obj = new T(); obj.FirstName = firstName; obj.LastName = lastName; return obj; } } public interface IPerson { string FirstName { get; set; } string LastName { get; set; } } public class PersonDisplayer { private IPerson _person; public PersonDisplayer(IPerson person) { _person = person; } public string SimpleDisplay() { return String.Format("{1}, {0}", _person.FirstName, _person.LastName); } public static string SimpleDisplay(IPerson person) { PersonDisplayer personDisplayer = new PersonDisplayer(person); return personDisplayer.SimpleDisplay(); } } public class Customer : IPerson { public string FirstName { get; set; } public string LastName { get; set; } public string Company { get; set; } } public class Employee : IPerson { public string FirstName { get; set; } public string LastName { get; set; } public int EmployeeNumber { get; set; } } } 

声明你的方法是这样的:

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

注意最后的附加约束。 然后在方法体中创build一个new实例:

 T obj = new T(); 

几个方法。

不指定types必须有一个构造函数:

 T obj = default(T); //which will produce null for reference types 

用一个构造函数:

 T obj = new T(); 

但是这需要条款:

 where T : new() 

为了扩展上面的答案,将where T:new()约束添加到generics方法将需要T有一个公共的,无参数的构造函数。

如果你想避免这种情况 – 而且在工厂模式下,你有时会迫使其他人通过你的工厂方法,而不是直接通过构造函数 – 那么另一种方法是使用reflection( Activator.CreateInstance... ),并保持默认的构造函数私人的。 但是,这当然会带来性能上的损失。

你需要新的 T(),但是你还需要在factory方法的where规范中添加, new()

有点老,但为其他人寻找解决scheme,也许这可能是有趣的: http : //daniel.wertheim.se/2011/12/29/c-generic-factory-with-support-for-private-constructors/

两个解决scheme 一个使用Activator,一个使用Compiled Lambdas。

 //Person has private ctor var person = Factory<Person>.Create(p => p.Name = "Daniel"); public static class Factory<T> where T : class { private static readonly Func<T> FactoryFn; static Factory() { //FactoryFn = CreateUsingActivator(); FactoryFn = CreateUsingLambdas(); } private static Func<T> CreateUsingActivator() { var type = typeof(T); Func<T> f = () => Activator.CreateInstance(type, true) as T; return f; } private static Func<T> CreateUsingLambdas() { var type = typeof(T); var ctor = type.GetConstructor( BindingFlags.Instance | BindingFlags.CreateInstance | BindingFlags.NonPublic, null, new Type[] { }, null); var ctorExpression = Expression.New(ctor); return Expression.Lambda<Func<T>>(ctorExpression).Compile(); } public static T Create(Action<T> init) { var instance = FactoryFn(); init(instance); return instance; } } 

而不是创build一个函数来实例化types

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

你可以这样做

 T obj = new T { FirstName = firstName, LastName = lastname }; 

使用工厂类来编译lambaexpression式的对象:我发现实例化generics的最快方法。

 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(); } } 

以下是我设定基准的步骤。

创build我的基准testing方法:

 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); } 

我也尝试使用工厂方法:

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

为了testing我创build了最简单的类:

 public class A { } 

要testing的脚本:

 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))"); 

结果超过1 000 000次迭代:

新的A():11ms

FactoryMethod A():275ms

FactoryClass A .Create():56ms

Activator.CreateInstance A():235ms

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

备注 :我已经使用.NET Framework 4.5和4.6 (等效结果)进行了testing。

您也可以使用reflection来获取对象的构造函数并实例化:

 var c = typeof(T).GetConstructor(); T t = (T)c.Invoke();