获取不同的列表值

我有一个C#应用程序,我想从一个Project对象列表,另一个包含不同对象的List。

我试过这个

  List model = notre_admin.Get_List_Project_By_Expert(u.Id_user); if (model != null) model = model.Distinct().ToList(); 

列表模型仍包含4个相同的对象Project

这是什么原因? 我该如何解决?

你需要在这里定义“相同”。 我猜你的意思是“具有相同的内容”,但这不是类的默认定义:默认定义是“是同一个实例”。

如果您希望“相同”表示“具有相同的内容”,则有两种选择:

  • 编写自定义比较器( IEqualityComparer )并将其作为参数提供给Distinct
  • Project上覆盖EqualsGetHashCode

还有像DistinctBy这样的自定义方法可用于很多地方,如果标识可以由单个属性(通常为Id )确定,则这种方法很有用 – 但不是在BCL中。 但是例如:

 if (model != null) model = model.DistinctBy(x => x.Id).ToList(); 

例如:

 public static IEnumerable DistinctBy(this IEnumerable items, Func selector) { var uniques = new HashSet(); foreach(var item in items) { if(uniques.Add(selector(item))) yield return item; } } 
 var newList = ( from x in model select new {Id_user= x.Id_user} ).Distinct(); 

或者你可以写这样的

 var list1 = model.DistinctBy(x=> x.Id_user); 

你如何定义相同的? 您应该使用此定义覆盖Project Equals (如果重写Equals也会覆盖GetHashCode )。 例如:

 public class Project { public int ProjectID { get; set; } public override bool Equals(object obj) { var p2 = obj as Project; if (p2 == null) return false; return this.ProjectID == m2.ProjectID; } public override int GetHashCode() { return ProjectID; } } 

否则你只是检查参考相等性 。

对象的引用不相等。 如果您希望能够在整个对象本身而不仅仅是属性上执行此操作,则必须实现IEqualityComparer或IEquatable

检查此示例:您需要使用Comparator或覆盖Equals()

 class Program { static void Main( string[] args ) { List items = new List(); items.Add( new Item( "A" ) ); items.Add( new Item( "A" ) ); items.Add( new Item( "B" ) ); items.Add( new Item( "C" ) ); items = items.Distinct().ToList(); } } public class Item { string Name { get; set; } public Item( string name ) { Name = name; } public override bool Equals( object obj ) { return Name.Equals((obj as Item).Name); } public override int GetHashCode() { return Name.GetHashCode(); } } 

这是基本相同的问题的答案 ,这将有所帮助。

说明:

Distinct()方法检查引用类型的引用相等性。 这意味着它在字面上寻找相同的对象,而不是包含相同值的不同对象。

致@Rex M.的学分

使用下面显示的方法之一是不是更简单:)? 您可以通过某个键对域对象进行分组,然后选择FirstOrDefault,如下所示。

更有趣的选择是创建一些Comparer适配器,它接收域对象并创建Comparer可以使用/开箱即用的其他对象。 基于比较器,您可以创建自定义linq扩展,如下面的示例所示。 希望能帮助到你 :)

 [TestMethod] public void CustomDistinctTest() { // Generate some sample of domain objects var listOfDomainObjects = Enumerable .Range(10, 10) .SelectMany(x => Enumerable .Range(15, 10) .Select(y => new SomeClass { SomeText = x.ToString(), SomeInt = x + y })) .ToList(); var uniqueStringsByUsingGroupBy = listOfDomainObjects .GroupBy(x => x.SomeText) .Select(x => x.FirstOrDefault()) .ToList(); var uniqueStringsByCustomExtension = listOfDomainObjects.DistinctBy(x => x.SomeText).ToList(); var uniqueIntsByCustomExtension = listOfDomainObjects.DistinctBy(x => x.SomeInt).ToList(); var uniqueStrings = listOfDomainObjects .Distinct(new EqualityComparerAdapter(x => x.SomeText)) .OrderBy(x=>x.SomeText) .ToList(); var uniqueInts = listOfDomainObjects .Distinct(new EqualityComparerAdapter(x => x.SomeInt)) .OrderBy(x => x.SomeInt) .ToList(); } 

自定义比较适配器:

 public class EqualityComparerAdapter : EqualityComparer where V : IEquatable { private Func _valueAdapter; public EqualityComparerAdapter(Func valueAdapter) { _valueAdapter = valueAdapter; } public override bool Equals(T x, T y) { return _valueAdapter(x).Equals(_valueAdapter(y)); } public override int GetHashCode(T obj) { return _valueAdapter(obj).GetHashCode(); } } 

自定义linq扩展(DistinctBy扩展方法的定义):

 // Embedd this class in some specific custom namespace public static class DistByExt { public static IEnumerable DistinctBy(this IEnumerable enumerator,Func valueAdapter) where V : IEquatable { return enumerator.Distinct(new EqualityComparerAdapter(valueAdapter)); } } 

测试用例中使用的域对象的定义:

 public class SomeClass { public string SomeText { get; set; } public int SomeInt { get; set; } } 
 List passData = (List)TempData["passData_Select_BankName_List"]; passData = passData?.DistinctBy(b=>b.BankNm).ToList(); 

它会工作……