LINQ: Utilisation .À l'exception de() sur les collections de différents types en les rendant convertible/comparables?
Donné deux listes de types différents, est-il possible de faire ces types convertibles entre ou comparables les uns aux autres (par exemple avec un TypeConverter ou similaire), de sorte qu'une requête LINQ pouvez comparer? J'ai vu d'autres questions similaires sur SI rien, mais que les points de rendre les types convertibles entre elles pour résoudre le problème.
Types De Collection:
public class Data
{
public int ID { get; set; }
}
public class ViewModel
{
private Data _data;
public ViewModel(Data data)
{
_data = data;
}
}
D'utilisation souhaitée:
public void DoMerge(ObservableCollection<ViewModel> destination, IEnumerable<Data> data)
{
//1. Find items in data that don't already exist in destination
var newData = destination.Except(data);
//...
}
Il semblerait logique que depuis que je sais comment comparer une instance de ViewModel à une instance de Données, je devrais être en mesure de fournir une comparaison logique que LINQ alors utiliser pour les requêtes comme .À l'exception de(). Est-ce possible?
- Pauvre vieux
for
boucle, il est donc utile, mais, hélas, il n'a jamais fait le one-liner gens heureux. - Je ne suis pas d'accord avec le sentiment que vous exprimez. Nous avons les moyens de l'écriture de code maintenant que de plus en plus clairement exprime l'intention, sans vous soucier du mécanisme.
for
exprime mécanismes et obscurcit l'intention. Le LINQ-fonction one-liners que vous êtes en dénonçant souvent (oui, pas toujours) mieux l'intention d'exprimer et de masquer les mécanismes. Cela conduit à un code qui est plus facile à comprendre et à maintenir. - alors que j'étais irrévérencieux, toutes les fonctions à vous jeter dans une projection comme vous ne sont confère une présomption d'intention.
- Je ne suis pas.
- simplement que je suis d'accord lorsque le LINQ peaux de contrôle simple-structure de base de la logique. Une projection à partir d'un type à l'autre n'est pas un de ces cas, l'omi. C'est pas plus clair ce qui se passe que dans
var newData = MeaningfulFunctionNameHere(destination, data);
Dans les deux cas, nous faisons une hypothèse sur ce qui se passe vraiment. En réalité, j'étais vraiment juste se moquer de LINQ est cool et s'applique partout de la foule. - Quel est le problème avec vous? LINQ est cool et ne s'appliquent partout. 😉
Vous devez vous connecter pour publier un commentaire.
Votre meilleur pari est de fournir une projection de
Data
àViewModel
de sorte que vous pouvez direoù
f
cartesData
àViewModel
. Vous aurez besoin d'unIEqualityComparer<Data>
trop.Je suppose que le fait de fournir une projection de
Data
àViewModel
est problématique, je vous propose donc une autre solution en plus de Jason.À l'exception utilise un hash jeu (si je me souviens bien), de sorte que vous pouvez obtenir des performances similaires en créant votre propre hashset. Je suis aussi en supposant que vous êtes l'identification
Data
objets que l'égalité lors de leurIDs
sont égaux.Vous pourriez avoir une autre utilisation pour une collection de "oldData" ailleurs dans la méthode, dans ce cas, vous voulez faire à la place. La mise en œuvre
IEquatable<Data>
sur votre classe de données, ou d'en créer un personnaliséIEqualityComparer<Data>
pour l'ensemble de hachage:ViewModel
a un constructeur qui prendData
!ViewModel
classe peut nécessiter beaucoup d'autres frais généraux dans sa construction. Philosophiquement, il semble étrange de créer un tas d'objets, il suffit de nous pouvons donc utiliserExcept
à sélectionner certains objets qui ne répondent pas à certains critères.Si vous utilisez ce :
Vous avez pour projet de 'données' de même type figurant dans "destination", mais à l'aide du code ci-dessous, vous pourriez se débarrasser de cette limitation :
Certains pourraient faire valoir que la mémoire inefficace en raison de l'utilisation d'un HashSet. Mais en réalité, l'Énumérable.À l'exception de la méthode du cadre est de faire de même avec une même classe interne appelé " Set " (j'ai pris un coup d'oeil par la décompilation).
Je sais que c'est tard, mais il y a une syntaxe plus simple à l'aide de la touche Func qui élimine le besoin d'un comparateur.
donc, avec les listes de la classe Foo et Bar
on peut courir Linq des déclarations comme
en gros, c'est une légère variation sur le dessus mais semble plus propre à moi.