IList méthode () où T: iClient ne peut pas ajouter objet client à la liste
-
09-09-2019 - |
Question
publics IList GetClientsByListofID (ids IList) où T: iClient { clients IList = new List (); clients.Add (nouveau client (3)); }
Je reçois une erreur de compilation ici:
ne peut pas convertir 'Bailey.Objects.Client' 'T'
L'objet client implémente l'interface iClient. Mon but ici est d'essayer et desserrer le couplage entre mes classes (apprentissage des choses DI atm). Je pensais que je peux dire qu'il peut utiliser tout type d'objet client et qui serait retourné.
Suis-je complètement à côté ici?
Merci
Hawkins Jon
La solution
Vous ne pouvez pas utiliser des contraintes génériques de cette façon. Comment le compilateur peut garantir que le paramètre de type est un Client
simplement parce qu'il implémente l'interface IClient
? Impossible de nombreux types mettre en œuvre cette interface?
Dans ce cas ( qui est dans le cas où vous devez travailler avec le type, pas l'interface ), il est préférable de limiter le paramètre de type avec le type se présente comme suit:
public IList<T> GetClientsByListofID<T>(IList<int> ids) where T : Client
{
IList<T> clients = new List<T>();
clients.Add(new Client(3));
// ...
}
et une fois que je fait me demande si vous avez besoin d'une méthode générique du tout:
public IList<Client> GetClientsByListofID(IList<int> ids)
{
IList<Client> clients = new List<Client>();
clients.Add(new Client(3));
// ...
}
Autres conseils
Client
est un IClient
.
T
est un IClient
.
Où avez-vous préciser que T
est un Client
? Nulle part!
Je pense que vous avez besoin d'un IClientFactory
ou IClientRepository
qui va créer / récupérer des instances de iClient pour vous. Vous serez alors en mesure d'utiliser différentes implémentations de cette usine / dépôt.
Essayez ceci:
public interface IClient
{
string Name { get; }
}
public class Client : IClient
{
public string Name { get; set; }
}
...
public IList<T> GetClientsByListofID<T>( IList<int> ids )
where T : class, IClient
{
var clients = new List<T>();
var client = new Client { Name = "bob" } as T;
clients.Add( client );
return clients;
}
Utilisation:
var clients = this.GetClientsByListOfID<Client>( null );
Votre problème n'est pas dans la contrainte
where T : IClient
mais plutôt dans l'utilisation de votre liste.
Vous ne pouvez pas dire:
IList<T> clients = new List<T>();
clients.Add( new Client(3));
vous pouvez dire ceci: (cela suppose que votre contrainte comprend « nouvelle »)
IList<T> clients = new List<T>();
clients.Add( new T());
dans ce cas, votre contrainte devrait alors être:
where T : new(), IClient
ou vous pouvez le faire, mais il ne serait pas utiliser les médicaments génériques du tout:
IList<T> clients = new List<Client>();
clients.Add( new Client(3));
La raison pour laquelle vous ne pouvez pas faire ce que vous essayez de faire est parce que le compilateur ne peut pas gaurantee que le type T sera de type client, ce qui est pourquoi il te donne l'erreur du compilateur. Il n'a rien à voir avec votre contrainte vraiment.
ce que vous faites ne fonctionne pas parce que dans C # 3.0 génériques ne prennent pas en charge covariance.
Vous pouvez faire quelque chose comme ceci:
interface IClient
{
int Id { get; set; }
}
class Client : IClient
{
public int Id { get; set; }
public Client() { }
}
// ...
public IList<T> GetClientsByListofID<T>(IList<int> ids) where T : IClient, new()
{
IList<T> clients = new List<T>();
clients.Add(new T() { Id = 3 });
// ...
return clients;
}
... mais je me demande si vous avez besoin génériques du tout.