Como posso instanciar o tipo T dentro do meu InstantiateType<T>
método abaixo?
Estou recebendo o erro: 'T' é um 'parâmetro de tipo', mas é usado como uma 'variável'. :
(Role para baixo para obter uma resposta refaturada)
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; }
}
}
RESPOSTA REFATORADA:
Obrigado por todos os comentários, eles me colocaram no caminho certo, isso é o que eu queria fazer:
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; }
}
}
Respostas:
Declare seu método assim:
Observe a restrição adicional no final. Em seguida, crie uma
new
instância no corpo do método:fonte
De várias maneiras.
Sem especificar o tipo deve ter um construtor:
Com um construtor:
Mas isso requer a cláusula:
fonte
Para ampliar as respostas acima, adicionar
where T:new()
restrição a um método genérico exigirá que T tenha um construtor público sem parâmetros.Se você quiser evitar isso - e em um padrão de fábrica, às vezes você força os outros a passarem pelo seu método de fábrica e não diretamente pelo construtor - então a alternativa é usar reflexão (
Activator.CreateInstance...
) e manter o construtor padrão privado. Mas isso vem com uma penalidade de desempenho, é claro.fonte
você quer novo T (), mas também precisa adicionar
, new()
àwhere
especificação do método de fábricafonte
Um pouco antigo, mas para quem procura uma solução, talvez isso possa ser do seu interesse: http://daniel.wertheim.se/2011/12/29/c-generic-factory-with-support-for-private-constructors/
Duas soluções. Um usando Activator e outro usando Compiled Lambdas.
fonte
Você também pode usar reflexão para buscar o construtor do objeto e instanciar dessa forma:
fonte
Usando uma classe de fábrica para construir seu objeto com a expressão lamba compilada: A maneira mais rápida que encontrei de instanciar o tipo genérico.
Aqui estão as etapas que segui para configurar o benchmark.
Crie meu método de teste de referência:
Também tentei usar um método de fábrica:
Para os testes, criei a classe mais simples:
O script para testar:
Observações : Eu testei usando o .NET Framework 4.5 e 4.6 (resultados equivalentes).
fonte
Em vez de criar uma função para instanciar o tipo
você poderia ter feito assim
fonte
new()
restrição ainda é necessária no tipo genérico para que sua resposta funcione.