¿Cómo puedo crear una instancia del tipo T dentro de mi InstantiateType<T>
método a continuación?
Recibo el error: 'T' es un 'parámetro de tipo' pero se usa como una 'variable'. :
(DESPLAZARSE HACIA ABAJO PARA OBTENER UNA RESPUESTA REFACTADA)
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; }
}
}
RESPUESTA REFACTORADA:
Gracias por todos los comentarios, me pusieron en el camino correcto, esto es lo que quería hacer:
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; }
}
}
Respuestas:
Declare su método de esta manera:
Observe la restricción adicional al final. Luego crea una
new
instancia en el cuerpo del método:fuente
Un par de formas.
Sin especificar el tipo debe tener un constructor:
Con un constructor:
Pero esto requiere la cláusula:
fuente
Para ampliar las respuestas anteriores, agregar
where T:new()
restricciones a un método genérico requerirá que T tenga un constructor público sin parámetros.Si desea evitar eso, y en un patrón de fábrica, a veces obliga a los demás a pasar por su método de fábrica y no directamente a través del constructor, entonces la alternativa es usar reflect (
Activator.CreateInstance...
) y mantener privado el constructor predeterminado. Pero esto viene con una penalización de rendimiento, por supuesto.fuente
desea un nuevo T (), pero también deberá agregar
, new()
a lawhere
especificación para el método de fábricafuente
Un poco antiguo pero para otros que buscan una solución, tal vez esto podría ser de interés: http://daniel.wertheim.se/2011/12/29/c-generic-factory-with-support-for-private-constructors/
Dos soluciones. Uno usando Activator y otro usando Lambdas compiladas.
fuente
También puede usar la reflexión para obtener el constructor del objeto y crear una instancia de esa manera:
fuente
Usando una clase de fábrica para construir su objeto con expresión lamba compilada: la forma más rápida que he encontrado para instanciar el tipo genérico.
Estos son los pasos que seguí para configurar el punto de referencia.
Crea mi método de prueba de referencia:
También intenté usar un método de fábrica:
Para las pruebas, he creado la clase más simple:
El guión para probar:
Observaciones : He probado con .NET Framework 4.5 y 4.6 (resultados equivalentes).
fuente
En lugar de crear una función para crear una instancia del tipo
podrías haberlo hecho así
fuente
new()
restricción sigue siendo necesaria en el tipo genérico para que su respuesta funcione.