Come posso mantenere il tipo quando uso LINQ. Seleziona in C #?

Sto cercando di restituire una serie di risultati distinti che vengono prima ritagliati usando la sottostringa, ma quando chiamo “Seleziona” lo converte in un tipo anonimo. Non riesco a ottenere questo per mantenere il tipo “Elenco”. Devo solo restituire i campi specificati nel metodo Seleziona.

public List GetFacilities() { var facilities = new List(); facilities = _facilityRepository.GetAll().ToList(); var facReturnList = facilities.Where(x => x.Fac_Name = "Something") .OrderBy(x => x.Fac_Name).ToList(); var facReturnList2 = facReturnList.Select(x => new { ID = x.Fac_Name.Substring(0, 6), Fac_Name = x.Fac_Name.Substring(0, 3) }) .Distinct().ToList(); return facReturnList2; } 

Ho provato ad aggiungere List dopo la new , ma dice che le proprietà ( ID e Fac_Name ) non sono definite in Facility.

Vuoi inizializzare le nuove istanze di Facility con i tuoi risultati?

 var facReturnList2 = facReturnList.Select(x => new Facility { ID = // ... ^ concrete type initializer 

Risposta alla modifica : all’interno dell’operatore Select , è necessario specificare il tipo di elementi che si desidera inizializzare, non la loro lista. Il tuo codice precedente sembra indicare che Fac_Name è definito in Facility , ma ovviamente non sarebbe definito in List .

Stai ricevendo un tipo anonimo perché lo stai creando.

 .Select(x => new { 

Se non lo vuoi, non farlo.

Se un tipo già esistente ha già il nome e le proprietà precise di cui hai bisogno, usa quello. Se nessun tipo ha ciò di cui hai bisogno, creane uno. Quindi puoi restituire un elenco appropriato o enumerabile di quel tipo.

 .Select(x => new YourDefinedType { 

Sembra che quello che vuoi veramente sia un metodo DistinctBy . Si desidera specificare alcuni metodi per indicare che un object è distinto, ma non si desidera che il risultato sia una raccolta di tale selezione, si desidera che il risultato finale sia l’object iniziale. LINQ non ha DistinctBy integrato, ma l’implementazione di uno è abbastanza semplice:

 public static IEnumerable DistinctBy(this IEnumerable source, Func keySelector, IEqualityComparer comparer = null) { comparer = comparer ?? EqualityComparer.Default; HashSet knownKeys = new HashSet(comparer); foreach (TSource element in source) { if (knownKeys.Add(keySelector(element))) { yield return element; } } } 

Usando che il tuo codice ora può diventare:

 public List GetFacilities() { return _facilityRepository.GetAll() .Where(x => x.Fac_Name == "Something") .DistinctBy(x => new { ID = x.Fac_Name.Substring(0, 6), Fac_Name = x.Fac_Name.Substring(0, 3) }) .OrderBy(x => x.Fac_Name) .ToList(); } 

Nel caso in cui si disponga di un IQueryable rispetto a un set di dati in memoria, è ansible utilizzare GroupBy per ottenere lo stesso comportamento. In Linq-to-objects utilizzando GroupBy sarebbe molto meno efficiente, ma per un provider di query non sarà come il database è in grado di ottimizzare questo.

 public List GetFacilities() { return _facilityRepository.GetAll() .Where(x => x.Fac_Name == "Something") .OrderBy(x => x.Fac_Name) .GroupBy(x => new { ID = x.Fac_Name.Substring(0, 6), Fac_Name = x.Fac_Name.Substring(0, 3) }) .Select(group => group.First()) .ToList(); } 

Il seguente codice sta indicando a linq di restituire un tipo anonimo:

 .Select(x => new { ID = x.Fac_Name.Substring(0, 6), Fac_Name = x.Fac_Name.Substring(0, 3) } 

Devi creare un corso per i tuoi risultati

 public class Result{ public string ID { get;set; } public string Fac_Name { get; set; } } //Then do .Select(x => new Result { ID = x.Fac_Name.Substring(0, 6), Fac_Name = x.Fac_Name.Substring(0, 3) } 

Questo garantisce che stai solo restituendo le informazioni di cui hai bisogno