LINQ.Distinct IEquatable对象不起作用(LINQ.Distinct on IEquatable object doesn't work)
我有一个继承自IEquatable <>的基类的对象。 到目前为止一切都很好,它适用于继承相同基类的其他对象。 但我在课堂上“RoomType”,当我使用“Attrbiutes”属性时似乎有问题。 下面你会看到我希望得到其他输出的类和测试。
我将问题缩小到RoomType.GetHashCode(),当我评论“SafeHashCode(Attributes)”时,返回预期的结果。
测试:
private static void QuickTest() { RoomType[] rooms = new RoomType[] { new RoomType { Attributes = new [] { "a", "b,"c"}, }, new RoomType { Attributes = new [] { "a", "b","c"}, } }; List<RoomType> result = rooms.Distinct().ToList(); //result contains 2 items, I was expecting 1 }
房型:
public class RoomType : EntityBase { public string OriginalRoomCode { get; set; } public Enum.RoomType RoomCode { get; set; } public IEnumerable<string> Attributes { get; set; } public override bool Equals(object obj) { RoomType other = obj as RoomType; if (other != null) return Equals(other); return false; } public override bool Equals(EntityBase obj) { RoomType y = (RoomType)obj; return SafeEqual(OriginalRoomCode, y.OriginalRoomCode) && SafeEqual(RoomCode, y.RoomCode) && SafeEqual(Attributes,y.Attributes); } public override int GetHashCode() { unchecked { return SafeHashCode(OriginalRoomCode) ^ SafeHashCode(RoomCode) ^ SafeHashCode(Attributes); } } public override object Clone() { return new RoomType { RoomCode = (Enum.RoomType)SafeClone(RoomCode), OriginalRoomCode = (string)SafeClone(OriginalRoomCode), Attributes = (IEnumerable<string>)SafeClone(Attributes) }; } }
EntityBase:
public abstract class EntityBase : IEquatable<EntityBase>, ICloneable { public bool SafeEqual<T>(T x, T y) { bool isXDefault = EqualityComparer<T>.Default.Equals(x, default(T)); bool isYDefault = EqualityComparer<T>.Default.Equals(y, default(T)); if (isXDefault && isYDefault) return true; if (isXDefault != isYDefault) return false; if (x is EntityBase) return x.Equals(y); IEnumerable<object> xEnumerable = x as IEnumerable<object>; IEnumerable<object> yEnumerable = y as IEnumerable<object>; if (xEnumerable != null && yEnumerable != null) { foreach (var yItem in yEnumerable) { bool match = false; foreach (var xItem in xEnumerable) { if(SafeEqual(xItem, yItem)) { match = true; break; } } if (!match) return false; } return true; } return x.Equals(y); } public int SafeHashCode<T>(T x) { if (EqualityComparer<T>.Default.Equals(x, default(T))) return 0; return x.GetHashCode(); } public object SafeClone<T>(T x) { //if x is null or default value if (EqualityComparer<T>.Default.Equals(x, default(T))) return default(T); //if x is of type EntityBase call clone() if (x is EntityBase) return (x as EntityBase).Clone(); //else the type is a default type return the value return x; } public abstract bool Equals(EntityBase other); public override abstract int GetHashCode(); public abstract override bool Equals(object obj); public abstract object Clone(); }
更新我能够通过在SafeHashCode(T x)中添加以下代码来解决它
IEnumerable<object> xEnumerable = x as IEnumerable<object>; if (xEnumerable != null) return xEnumerable.Aggregate(17, (acc, item) => acc * 19 + SafeHashCode(item));
I've an object that inherites from a base class that inherits from IEquatable<>. So far so good and it works for other objects that inherit the same base class. But I have on class "RoomType" where there seems to be a problem when I use the "Attrbiutes" property. Below you see the classes and a test where I expect other output that given.
I narrowed the problem down to something with the RoomType.GetHashCode(), when I comment "SafeHashCode(Attributes)" the expected result is returned.
Test:
private static void QuickTest() { RoomType[] rooms = new RoomType[] { new RoomType { Attributes = new [] { "a", "b,"c"}, }, new RoomType { Attributes = new [] { "a", "b","c"}, } }; List<RoomType> result = rooms.Distinct().ToList(); //result contains 2 items, I was expecting 1 }
RoomType:
public class RoomType : EntityBase { public string OriginalRoomCode { get; set; } public Enum.RoomType RoomCode { get; set; } public IEnumerable<string> Attributes { get; set; } public override bool Equals(object obj) { RoomType other = obj as RoomType; if (other != null) return Equals(other); return false; } public override bool Equals(EntityBase obj) { RoomType y = (RoomType)obj; return SafeEqual(OriginalRoomCode, y.OriginalRoomCode) && SafeEqual(RoomCode, y.RoomCode) && SafeEqual(Attributes,y.Attributes); } public override int GetHashCode() { unchecked { return SafeHashCode(OriginalRoomCode) ^ SafeHashCode(RoomCode) ^ SafeHashCode(Attributes); } } public override object Clone() { return new RoomType { RoomCode = (Enum.RoomType)SafeClone(RoomCode), OriginalRoomCode = (string)SafeClone(OriginalRoomCode), Attributes = (IEnumerable<string>)SafeClone(Attributes) }; } }
EntityBase:
public abstract class EntityBase : IEquatable<EntityBase>, ICloneable { public bool SafeEqual<T>(T x, T y) { bool isXDefault = EqualityComparer<T>.Default.Equals(x, default(T)); bool isYDefault = EqualityComparer<T>.Default.Equals(y, default(T)); if (isXDefault && isYDefault) return true; if (isXDefault != isYDefault) return false; if (x is EntityBase) return x.Equals(y); IEnumerable<object> xEnumerable = x as IEnumerable<object>; IEnumerable<object> yEnumerable = y as IEnumerable<object>; if (xEnumerable != null && yEnumerable != null) { foreach (var yItem in yEnumerable) { bool match = false; foreach (var xItem in xEnumerable) { if(SafeEqual(xItem, yItem)) { match = true; break; } } if (!match) return false; } return true; } return x.Equals(y); } public int SafeHashCode<T>(T x) { if (EqualityComparer<T>.Default.Equals(x, default(T))) return 0; return x.GetHashCode(); } public object SafeClone<T>(T x) { //if x is null or default value if (EqualityComparer<T>.Default.Equals(x, default(T))) return default(T); //if x is of type EntityBase call clone() if (x is EntityBase) return (x as EntityBase).Clone(); //else the type is a default type return the value return x; } public abstract bool Equals(EntityBase other); public override abstract int GetHashCode(); public abstract override bool Equals(object obj); public abstract object Clone(); }
Update I was able to fix it by adding the following code inside SafeHashCode(T x)
IEnumerable<object> xEnumerable = x as IEnumerable<object>; if (xEnumerable != null) return xEnumerable.Aggregate(17, (acc, item) => acc * 19 + SafeHashCode(item));
原文:https://stackoverflow.com/questions/43232457
最满意答案
在
cellForRowAtIndexPath
方法中像这样设置按钮文本首先删除它cell.dbColumnOrder.titleLabel?.text = column.order
替换它
cell.dbColumnOrder.setTitle("\(column.order)", for: .normal)
还有一件事需要增加
cell.dbColumnOrder
宽度。希望它有效
In
cellForRowAtIndexPath
method Set button text like this way First remove thiscell.dbColumnOrder.titleLabel?.text = column.order
Replace this
cell.dbColumnOrder.setTitle("\(column.order)", for: .normal)
And one more thing you need to increase
cell.dbColumnOrder
width.Hope it works
相关问答
更多-
不要直接为按钮设置图像和文本。 使用func set
(forState:)和func ForState:)方法。 cell.myImageButton.setImage(catch.image, forState:.Normal) 和 cell.myImageButton.setTitle("", forState:.Normal) 代码变成了 cell.myImageButton.setImage(catch.image, forState:.Normal) if catch.image ... -
好的我找到了。 令人难以置信的到底有多简单! 我刚刚添加了一个其他声明: func onLoadSet(){ identifier = "\(textLabel!.text!)\(rowCount)" //Set state from stored State if var storedToDoItems: AnyObject! = NSUserDefaults.standardUserDefaults().objectForKey("packItems") { if storedToDoItem ...
-
在tableview单元格中更改UIImageView显示/尺寸(Change UIImageView display/dimensions within a tableview cell)[2023-06-22]
不是以编程方式添加约束,而是在Interface Builder中指定宽度,并在代码中创建宽度约束的出口。 然后,在将单元格出列后,您可以将宽度约束的constant属性更改为0(如果您希望它隐藏),或者更改为您想要扩展宽度的任何属性。 编辑:此外,我在@MuhammadZohaibEhsan在下面的评论中建议,将约束的constant属性重置为单元格的prepareForReuse()方法中的原始大小。 Instead of adding the constraint programmatically, ... -
这种表格单元格由两个标签组成,一个在左侧,另一个在右侧,蓝色文本。 尝试设置标签单元的背景颜色: tableCell.textLabel.backgroundColor = ... tableCell.detailTextLabel.backgroundColor = ... 编辑:您还需要设置tableCell的contentView的背景颜色。 tableCell.contentView.backgroundColor = ... 编辑2:以下代码还可确保背景颜色延伸至附件 UIColor *bgC ...
-
在cellForRowAtIndexPath方法中像这样设置按钮文本首先删除它 cell.dbColumnOrder.titleLabel?.text = column.order 替换它 cell.dbColumnOrder.setTitle("\(column.order)", for: .normal) 还有一件事需要增加cell.dbColumnOrder宽度。 希望它有效 In cellForRowAtIndexPath method Set button text like this way ...
-
使用此代码设置表格视图单元格按钮的操作 [(UIButton *)[cell.contentView viewWithTag:104] addTarget:self action:@selector(selectButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; 并使用sender定义这样的方法 -(void)selectButtonPressed:(id)sender { NSLog(@"Met ...
-
经过对这一次的惊人努力之后,我找到了解决方案。 关于以下内容: Swift:Static UITableViewCell中的TableView 解决问题的地方说: 通过试验这个我可以确定,你不能使用相同的UITableViewController作为两个表视图的数据源和委托。 使用静态表视图,您根本不应该实现数据源方法。 奇怪的是,即使我断开数据源并委托我的静态表视图和表视图控制器之间的连接,该表视图仍然在我的表视图控制器类中调用numberOfRowsInSection。 如果我在代码中将数据源显式设置为 ...
-
你需要在你的cellForRowAtIndexPath方法中向前看,并且正如Paulw11推荐的那样,在插入单元格后调用reloadRowsAtIndexPaths : import UIKit struct MyMessage { let sender: String let text: String } class MyTableViewCell: UITableViewCell { var message: MyMessage? var showProfileIma ...
-
您可以通过IndexPath使用存储的lastCell简单地创建一个IndexPath : IndexPath(row: self.lastCell, section: 0) 如果有多个部分,您只需要插入最后一部分而不是0部分。 You can simply create an IndexPath using your stored lastCell via: IndexPath(row: self.lastCell, section: 0) If there is more than one sect ...
-
更改tableview单元格项目(Changing tableview cells items)[2022-12-07]
您必须在按钮单击时分配表视图的tag属性。 - (IBAction) btnClick1:(id)sender { tableview.tag = 200; [tableview reload]; } 现在在你的所有表视图的委托方法中检查表视图的tag就像 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if([tableView tag] == 20 ...