Wie kann ich den Typ T in meiner folgenden InstantiateType<T>
Methode instanziieren ?
Ich erhalte die Fehlermeldung: 'T' ist ein 'Typparameter', wird aber wie eine 'Variable' verwendet. ::
(SCROLLEN SIE FÜR REFACTORED ANTWORT NACH UNTEN)
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; }
}
}
REFAKTORIERTE ANTWORT:
Vielen Dank für alle Kommentare, sie haben mich auf den richtigen Weg gebracht, das wollte ich tun:
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; }
}
}
Antworten:
Deklarieren Sie Ihre Methode folgendermaßen:
Beachten Sie die zusätzliche Einschränkung am Ende. Erstellen Sie dann eine
new
Instanz im Methodenkörper:quelle
Ein paar Möglichkeiten.
Ohne Angabe des Typs muss ein Konstruktor vorhanden sein:
Mit einem Konstruktor:
Dies erfordert jedoch die Klausel:
quelle
Um die obigen Antworten zu erweitern,
where T:new()
erfordert das Hinzufügen einer Einschränkung zu einer generischen Methode, dass T einen öffentlichen, parameterlosen Konstruktor hat.Wenn Sie dies vermeiden möchten - und in einem Factory-Muster manchmal die anderen dazu zwingen, Ihre Factory-Methode und nicht direkt den Konstruktor zu durchlaufen -, besteht die Alternative darin, Reflection (
Activator.CreateInstance...
) zu verwenden und den Standardkonstruktor privat zu halten. Aber das bringt natürlich eine Leistungsstrafe mit sich.quelle
Sie möchten ein neues T (), müssen aber auch
, new()
diewhere
Spezifikation für die Factory-Methode ergänzenquelle
Ein bisschen alt, aber für andere, die nach einer Lösung suchen, könnte dies vielleicht von Interesse sein: http://daniel.wertheim.se/2011/12/29/c-generic-factory-with-support-for-private-constructors/
Zwei Lösungen. Eine mit Activator und eine mit Compiled Lambdas.
quelle
Sie können auch Reflection verwenden, um den Konstruktor des Objekts abzurufen und auf diese Weise zu instanziieren:
quelle
Verwenden einer Factory-Klasse zum Erstellen Ihres Objekts mit kompiliertem Lamba-Ausdruck: Der schnellste Weg, den generischen Typ zu instanziieren.
Hier sind die Schritte, die ich ausgeführt habe, um den Benchmark festzulegen.
Erstellen Sie meine Benchmark-Testmethode:
Ich habe auch versucht, eine Factory-Methode zu verwenden:
Für die Tests habe ich die einfachste Klasse erstellt:
Das zu testende Skript:
Anmerkungen : Ich habe sowohl .NET Framework 4.5 als auch 4.6 getestet (äquivalente Ergebnisse).
quelle
Anstatt eine Funktion zum Instanziieren des Typs zu erstellen
du hättest es so machen können
quelle
new()
Einschränkung für den generischen Typ wird weiterhin benötigt, damit Ihre Antwort funktioniert.