我来到这个网站,在Dictionary中搜索对象比较,我开始知道重写GetHashCode和Equals是在C#中进行对象比较的必要条件。 这是我尝试使用FOREACH迭代方法解决的一段代码。但是由于性能问题,我的Boss说在不使用任何迭代(可能使用containskey或containsvalue方法)的情况下也这样做。任何帮助都非常受欢迎..
public class employee
{
public string empname { get; set; }
public string location { get; set; }
public double kinid { get; set; }
public double managerKin { get; set; }
public override bool Equals(object obj)
{
return base.Equals(obj);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
}
public class manager
{
public string managername { get; set; }
public double kinid { get; set; }
public override int GetHashCode()
{
return 17 * managername.GetHashCode() + kinid.GetHashCode();
}
}
public class program
{
public static void Main()
{
employee emp = new employee();
employee emp2 = new employee();
manager mng = new manager();
manager mng2 = new manager();
emp.empname = "Deepak";
emp.location = "Pune";
emp.kinid = 36885;
emp.managerKin = 007;
emp2.empname = "Astha";
emp2.location = "Pune";
emp2.kinid = 30000;
emp2.managerKin = 007;
mng.kinid = 007;
mng.managername = "Gaurav";
mng2.kinid = 001;
mng2.managername = "Surya";
Dictionary<employee, manager> relations = new Dictionary<employee, manager>();
relations.Add(emp, mng);
relations.Add(emp2, mng2);
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("The Manager details are :");
foreach (var element in relations)
Console.WriteLine(" \n KINID : {0} \n Manager'sName : {1}",element.Value.kinid, element.Value.managername);
Console.WriteLine("Enter the details of the manager..");
Console.ForegroundColor = ConsoleColor.Gray;
Console.Write("\nManager's Kin : ");
double mkin = Convert.ToDouble(Console.ReadLine());
Console.Write("Manager's Name : ");
string mname = Console.ReadLine();
manager mng1 = new manager();
mng1.kinid = mkin;
mng1.managername = mname;
int hashvalue = 17 * mname.GetHashCode() + mkin.GetHashCode();
#region BY USING FOREACH LOOP
int i = 0;
foreach (var element in relations)
{
if (element.Value.GetHashCode() == hashvalue)
{
i += 1;
if (i == 1)
{
Console.WriteLine("The Following employees report to the Manager : {0}", mname);
}
Console.WriteLine(element.Key.empname + " " + element.Key.kinid + " " + element.Key.location + " " + element.Key.managerKin);
}
}
if (i == 0)
{
Console.WriteLine("sorry the manager's details you entered \"{0}\" \"{1}\" does not exist in our database..", mng1.managername, mng1.kinid);
}
#endregion
Console.ReadLine();
}
}
答案 0 :(得分:3)
这是代码
#region USING DICTIONARY TO STORE CLASS OBJECTS (check employee existence and print manager's name)
public class employee
{
public string empname { get; set; }
public string location { get; set; }
public double kinid { get; set; }
public double managerKin { get; set; }
//public override bool Equals(object obj) // ANY OF THE TWO EQUALS METHOD WORKS.
//{
// employee otheremployee;
// otheremployee = (employee)obj;
// return (otheremployee.kinid == this.kinid && otheremployee.location == this.location && otheremployee.empname == this.empname && otheremployee.managerKin == this.managerKin);
//}
public override bool Equals(object obj) //When Running this entire code, put a break-point on both the Equals() and GetHashCode() methods, and see the execution flow.
{
employee otheremployee;
otheremployee = (employee)obj;
return (obj.GetHashCode() == otheremployee.GetHashCode());
}
public override int GetHashCode() //When Running this entire code, put a break-point on both the Equals() and GetHashCode() methods, and see the execution flow.
{
//int temp = base.GetHashCode(); // DONT USE THIS
//return base.GetHashCode();
int temp = empname.GetHashCode() + location.GetHashCode() + kinid.GetHashCode() + managerKin.GetHashCode();
return temp;
}
}
public class manager
{
public string managername { get; set; }
public double kinid { get; set; }
public override int GetHashCode()
{
return base.GetHashCode();
}
public override bool Equals(object obj)
{
return base.Equals(obj);
}
}
public class program
{
public static void Main()
{
employee emp = new employee();
employee emp2 = new employee();
manager mng = new manager();
manager mng2 = new manager();
emp.empname = "Deepak";
emp.location = "Pune";
emp.kinid = 36885;
emp.managerKin = 007;
emp2.empname = "Astha";
emp2.location = "Pune";
emp2.kinid = 30000;
emp2.managerKin = 001;
mng.kinid = 007;
mng.managername = "Gaurav";
mng2.kinid = 001;
mng2.managername = "Surya";
Dictionary<employee, manager> relations = new Dictionary<employee, manager>();
relations.Add(emp, mng); // put a BreakPoint here and see the execution flow
relations.Add(emp2, mng2);// put a BreakPoint here and see the execution flow
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("The Employee details are :");
foreach (var element in relations)
Console.WriteLine(" \n Employee Name : {0} \n Location : {1} \n Employee KinId : {2} \n Manager's KinId : {3} ",
element.Key.empname, element.Key.location, element.Key.kinid, element.Key.managerKin);
Console.WriteLine("Enter the details of the Employee..");
Console.ForegroundColor = ConsoleColor.Gray;
Console.Write("\nEmployee Name : "); string ename = Console.ReadLine();
Console.Write("Location : "); string elocn = Console.ReadLine();
Console.Write("Employee KinId : "); double ekinid = Convert.ToDouble(Console.ReadLine());
Console.Write("Manager's ID : "); double emngr = Convert.ToDouble(Console.ReadLine());
employee emp1 = new employee();
emp1.empname = ename;
emp1.location = elocn;
emp1.kinid = ekinid;
emp1.managerKin = emngr;
int i = 0; // This variable acts as a indicator to find whether the Employee Key exists or not.
if (relations.ContainsKey(emp1)) //Put a break point here and see the execution flow.
{
Console.WriteLine("the Employee : {0} exists..", emp1.empname);
Console.WriteLine("the Employee reports to the following manager : {0} \n and the Manager's KinId is {1}.", (relations[emp1]).managername, relations[emp1].kinid);
i = 1;
Console.ReadLine();
}
if (i == 0)
{
Console.WriteLine("the details of the employee named {0} does not exist !!", emp1.empname);
Console.ReadLine();
}
#endregion
答案 1 :(得分:1)
要搜索字典中的元素,您可以使用ContainsKey,ContainsValue方法或只编写LINQ查询
var dict = (from pair in relations
where pair.Value.Equals(mng1)
select pair).ToDictionary<employee,manager>();
答案 2 :(得分:1)
Dictionary.ContainsKey(employee)
在这里没有帮助,因为员工是“未知”值,而Contains
无效,因为它需要KeyValuePair<employee,manager>
再次......没有员工知道。 ContainsValue(manager)
无效,因为它不会返回任何键和因为它不是键,而是O(n)
操作,而不是O(1)
之类的ContainsKey
{1}}!
使用当前结构,唯一的方法是使用某种形式的循环,虽然我会这样写:
// Key is Employee, Value is Manager
// This is O(n)
var theEmployees = relations
.Where(rel => rel.Value.Equals(theManager))
.Select(rel => rel.Key);
这仅在manager
获得有效Equals
实施后才有效。请注意,哈希码并未在所有中使用。 (因为不同的对象可能共享相同的哈希代码,所以仅比较哈希代码不能替代Equals
或{ {1}}或==
! - 取决于哪一个合适。)
如果有许多这样的查询,那么初始结构可以“反转”。
CompareTo
仅当// Build a reverse lookup-up
var employeesForManager = relations
.GroupBy(rel => rel.Value) // group on Manager
.ToDictionary(g => g.Key, g => g); // Key is the group's Manager
// This is O(1), but only valid AFTER employeesForManager is [re-]generated
var theEmployees = employeesForManager[theManager]
具有有效manager
和Equals
实施时,此功能才有效。 (GetHashCode是必需的,因为GetHashCode
个对象被用作新词典的键。)
至于哪个“更好” - 嗯,这取决于。例如,创建反向查找仅使用一次是愚蠢的。在出现性能问题之前没有性能问题:编写干净的代码和配置文件。
快乐的编码。
答案 3 :(得分:1)
为了能够比较2个实例的相等性,您应该重写Equals方法,并且实现IEquatable<T>
也是一种好习惯。
当您重写等于时,您还应该重写GetHashcode(当您将实例放入字典中以计算存储桶时使用此方法。)
你不应该使用GetHashcode
来比较对象的2个实例是否相等;相反,您应该使用Equals
(或EqualityComparer
,它也将使用Equals方法。)
如果您已经实现了GetHashCode和Equals,那么您可以通过执行以下操作来确定字典是否包含特定实例:
var myDictionary<int, Manager> = new Dictionary<int,Manager>();
myDictionary.ContainsKey (someKey)
或
var mySet = new HashSet<Manager>();
mySet.Contains(someManagerObject);
答案 4 :(得分:0)
我相信你的最终回复中有一个错误。
该行
return(obj.GetHashCode()== otheremployee.GetHashCode());
可能应该是
return(this.GetHashCode()== otheremployee.GetHashCode());
这样你就可以比较这个对象和另一个对象的哈希码。正如您在回复中所写的那样,您似乎正在将另一个对象与自身进行比较。