Comment puis-je instancier le type T dans ma InstantiateType<T>
méthode ci-dessous?
J'obtiens l'erreur: «T» est un «paramètre de type» mais est utilisé comme une «variable». :
(DÉFILEZ VERS LE BAS POUR UNE RÉPONSE REFACTORÉE)
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; }
}
}
RÉPONSE RÉFACTURÉE:
Merci pour tous les commentaires, ils m'ont mis sur la bonne voie, c'est ce que je voulais faire:
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; }
}
}
Réponses:
Déclarez votre méthode comme ceci:
Notez la contrainte supplémentaire à la fin. Créez ensuite une
new
instance dans le corps de la méthode:la source
Deux façons.
Sans spécifier le type doit avoir un constructeur:
Avec un constructeur:
Mais cela nécessite la clause:
la source
Pour prolonger les réponses ci-dessus, l'ajout d'une
where T:new()
contrainte à une méthode générique exigera que T ait un constructeur public sans paramètre.Si vous voulez éviter cela - et dans un modèle de fabrique, vous forcez parfois les autres à passer par votre méthode de fabrique et non directement par le constructeur - alors l'alternative est d'utiliser Reflection (
Activator.CreateInstance...
) et de garder le constructeur par défaut privé. Mais cela vient avec une pénalité de performance, bien sûr.la source
vous voulez un nouveau T (), mais vous devrez également ajouter
, new()
à lawhere
spécification de la méthode d'usinela source
Un peu vieux mais pour d'autres à la recherche d'une solution, cela pourrait peut-être être intéressant: http://daniel.wertheim.se/2011/12/29/c-generic-factory-with-support-for-private-constructors/
Deux solutions. Un utilisant Activator et un utilisant des Lambdas compilés.
la source
Vous pouvez également utiliser la réflexion pour récupérer le constructeur de l'objet et l'instancier de cette façon:
la source
Utilisation d'une classe d'usine pour construire votre objet avec une expression lamba compilée: Le moyen le plus rapide que j'ai trouvé pour instancier un type générique.
Voici les étapes que j'ai suivies pour configurer le benchmark.
Créer ma méthode de test de référence:
J'ai également essayé d'utiliser une méthode d'usine:
Pour les tests, j'ai créé la classe la plus simple:
Le script à tester:
Remarques : J'ai testé à la fois .NET Framework 4.5 et 4.6 (résultats équivalents).
la source
Au lieu de créer une fonction pour instancier le type
tu aurais pu le faire comme ça
la source
new()
contrainte est toujours nécessaire sur le type générique pour que votre réponse fonctionne.