IList metodo () dove T: iClient non può aggiungere oggetto client alla lista
-
09-09-2019 - |
Domanda
pubbliche IList GetClientsByListofID (IDS IList) dove T: iClient { clienti IList = new List (); clients.Add (nuovo Cliente (3)); }
sto ottenendo un errore di compilazione qui:
non può convertire da 'Bailey.Objects.Client' a 'T'
L'oggetto client implementa l'interfaccia iClient. Il mio obiettivo qui è quello di provare e allentare l'accoppiamento tra le mie classi (apprendimento DI roba atm). Stavo pensando che posso dire che può utilizzare qualsiasi tipo di oggetto client e che sarebbe tornato.
Sono io di base completamente fuori qui?
Grazie
Jon Hawkins
Soluzione
Non è possibile utilizzare i vincoli generici in questo modo. Come può il compilatore garantisce che il parametro di tipo è un Client
semplicemente perché implementa l'interfaccia IClient
? Potrebbero non molti tipi implementare tale interfaccia?
In questo caso ( che è nel caso in cui è necessario lavorare con il tipo, non è l'interfaccia ) è meglio limitare il parametro di tipo con il tipo di per sé in questo modo:
public IList<T> GetClientsByListofID<T>(IList<int> ids) where T : Client
{
IList<T> clients = new List<T>();
clients.Add(new Client(3));
// ...
}
e una volta a fare che mi chiedo se avete bisogno di un metodo generico a tutti:
public IList<Client> GetClientsByListofID(IList<int> ids)
{
IList<Client> clients = new List<Client>();
clients.Add(new Client(3));
// ...
}
Altri suggerimenti
Client
è un IClient
.
T
è un IClient
.
Da dove si specifica che T
è un Client
? Da nessuna parte!
Credo che hai bisogno di una IClientFactory
o IClientRepository
che creerà / recuperare le istanze iClient per voi. Sarà quindi in grado di utilizzare diverse implementazioni di questa fabbrica / repository.
Prova questo:
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;
}
Utilizzo:
var clients = this.GetClientsByListOfID<Client>( null );
Il problema non è nel vincolo
where T : IClient
ma piuttosto nell'uso della tua lista.
Non si può dire questo:
IList<T> clients = new List<T>();
clients.Add( new Client(3));
Si può dire questo: (questo presuppone che il vincolo include "nuovo")
IList<T> clients = new List<T>();
clients.Add( new T());
in questo caso il vincolo sarebbe quindi bisogno di essere:
where T : new(), IClient
o si potrebbe fare questo, ma non avrebbe usato farmaci generici a tutti:
IList<T> clients = new List<Client>();
clients.Add( new Client(3));
Il motivo per cui non si può fare quello che stai cercando di fare è perché il compilatore non è in grado gaurantee che il tipo T sarà di tipo client, è per questo che si sta dando l'errore del compilatore. Non ha nulla a che fare con il vostro vincolo davvero.
Che cosa il vostro stanno facendo non funziona perché in C # 3.0 generici non supportano covarianza.
Si potrebbe fare qualcosa di simile:
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;
}
... ma mi chiedo se avete bisogno di farmaci generici a tutti.