C#比较参考值和值
我在向它传递值时遇到了这个方法的问题 注意:在我看来,使用此功能的系统是一个黑匣子,因此无法更改 问题是,将相同的值(如字符串、布尔值、对象等)传递给该方法将表示它们不相等,即使这些值相同。我假设这是因为一个是引用,而另一个是值,因此它们“不同” 结果是单元测试全部通过。。。正如“预期的” 因此,当我进行测试时,它会按预期工作,但当我连接到系统的其余部分并进行调试以便可以看到“field”和“value”的值时,它不会工作C#比较参考值和值,c#,reference,C#,Reference,我在向它传递值时遇到了这个方法的问题 注意:在我看来,使用此功能的系统是一个黑匣子,因此无法更改 问题是,将相同的值(如字符串、布尔值、对象等)传递给该方法将表示它们不相等,即使这些值相同。我假设这是因为一个是引用,而另一个是值,因此它们“不同” 结果是单元测试全部通过。。。正如“预期的” 因此,当我进行测试时,它会按预期工作,但当我连接到系统的其余部分并进行调试以便可以看到“field”和“value”的值时,它不会工作 以前有人尝试过类似的方法吗?您缺少了相等比较器 正如您在本例中看到的,即
以前有人尝试过类似的方法吗?您缺少了相等比较器 正如您在本例中看到的,即使等于,输出也将为false:
class Program
{
static void Main(string[] args)
{
Pizza pizza1 = new Pizza(1);
Pizza pizza2 = new Pizza(1);
bool equal = AreEqual(pizza1, pizza2);
Console.WriteLine(equal);
}
public static bool AreEqual<T>(T field, T value)
{
return EqualityComparer<T>.Default.Equals(field, value);
}
}
public class Pizza
{
public Pizza(int slices)
{
Slices = slices;
}
public int Slices { get; set; }
}
类程序
{
静态void Main(字符串[]参数)
{
比萨饼1=新比萨饼(1);
比萨饼2=新比萨饼(1);
bool equal=arequal(pizza1,pizza2);
控制台写入线(相等);
}
公共静态布尔值相等(T字段,T值)
{
返回EqualityComparer.Default.Equals(字段,值);
}
}
公共级比萨饼
{
公共披萨(整块)
{
切片=切片;
}
公共整数切片{get;set;}
}
输出:
假的
这样,即使使用自定义对象,它也可以工作:
class Program
{
static void Main(string[] args)
{
Pizza pizza1 = new Pizza(1);
Pizza pizza2 = new Pizza(1);
bool equal = AreEqual(pizza1, pizza2, new PizzaComparer());
Console.WriteLine(equal);
}
public static bool AreEqual<T>(T field, T value, IEqualityComparer<T> equalityComparer)
{
return equalityComparer.Equals(field, value);
}
}
public class Pizza
{
public Pizza(int slices)
{
Slices = slices;
}
public int Slices { get; set; }
}
public class PizzaComparer : IEqualityComparer<Pizza>
{
public bool Equals(Pizza pizza1, Pizza pizza2)
{
return pizza1.Slices == pizza2.Slices;
}
public int GetHashCode(Pizza pizza)
{
return pizza.Slices.GetHashCode();
}
}
类程序
{
静态void Main(字符串[]参数)
{
比萨饼1=新比萨饼(1);
比萨饼2=新比萨饼(1);
bool equal=AreEqual(pizza1、pizza2、新PizzaComparer());
控制台写入线(相等);
}
公共静态布尔值相等(T字段、T值、IEqualityComparer相等Comparer)
{
返回equalityComparer.Equals(字段,值);
}
}
公共级比萨饼
{
公共披萨(整块)
{
切片=切片;
}
公共整数切片{get;set;}
}
公共类比萨饼比较器:IEqualityComparer
{
公共布尔等于(比萨披萨1、比萨披萨2)
{
返回pizza1.Slices==pizza2.Slices;
}
公共整数GetHashCode(比萨饼)
{
返回pizza.Slices.GetHashCode();
}
}
输出:
真的
为什么
字段
是通过引用传递的?您不会更改代码中的引用。调试时看到的值是什么?您正在比较浮点数,而使用普通的equals无法真正进行比较。相反,你应该在这里使用一些宽容。通过这种方式,您可以在单元测试中将12.3
与12.3
进行比较,但是当您的值之间存在细微差异时,例如12.300000001
(可能来自db表)和12.2999999993
(来自不同的表)。自定义类型可能无法实现相等比较。然后它将退回到默认行为,这可能是引用相等。然后,具有相同内容的对象可能会被视为“不相等”,因为它们不是相同的对象。类似的字符串:他们可能被拘留或没有。因此,可以有相同的字符串(值),但有两个不同的引用。如果您随后检查引用相等性,它将失败。请发布一个显示问题的说明,而不是显示它按您希望的方式工作的代码。我看不出你的代码有什么问题,所以我假设问题在其他地方,在你没有发布的代码中,所以发布一个完整(但简短)的例子,说明这个问题,这样我们就可以自己测试它了。你说这个问题存在于字符串、布尔和对象。对于您自己的类型,您需要为EqualityComparer.Default
实现一个接口,以便能够对它们进行比较,但对于字符串和bool,这应该可以正常工作。他在问题中说,对于字符串、bool等类型,也存在此问题,这些类型都实现了此接口。
[TestMethod]
public void IsDirtyString()
{
var tc = new Program();
var field = "Germany";
var value = "United States";
var result = tc.AreEqual(ref field, value);
Assert.IsFalse(result);
}
[TestMethod]
public void IsNotDirtyString()
{
var tc = new Program();
var field = "Nepal";
var value = "Nepal";
var result = tc.AreEqual(ref field, value);
Assert.IsTrue(result);
}
[TestMethod]
public void IsDirtyDouble()
{
var tc = new Program();
var field = 11.2;
var value = 12.3;
var result = tc.AreEqual(ref field, value);
Assert.IsFalse(result);
}
[TestMethod]
public void IsNotDirtyDouble()
{
var tc = new Program();
var field = 12.3;
var value = 12.3;
var result = tc.AreEqual(ref field, value);
Assert.IsTrue(result);
}
[TestMethod]
public void IsDirtyInt()
{
var tc = new Program();
var field = 12;
var value = 15;
var result = tc.AreEqual(ref field, value);
Assert.IsFalse(result);
}
[TestMethod]
public void IsNotDirtyInt()
{
var tc = new Program();
var field = 12;
var value = 12;
var result = tc.AreEqual(ref field, value);
Assert.IsTrue(result);
}
[TestMethod]
public void IsDirtyBool()
{
var tc = new Program();
var field = true;
var value = false;
var result = tc.AreEqual(ref field, value);
Assert.IsFalse(result);
}
[TestMethod]
public void IsNotDirtyBool()
{
var tc = new Program();
var field = true;
var value = true;
var result = tc.AreEqual(ref field, value);
Assert.IsTrue(result);
}
class Program
{
static void Main(string[] args)
{
Pizza pizza1 = new Pizza(1);
Pizza pizza2 = new Pizza(1);
bool equal = AreEqual(pizza1, pizza2);
Console.WriteLine(equal);
}
public static bool AreEqual<T>(T field, T value)
{
return EqualityComparer<T>.Default.Equals(field, value);
}
}
public class Pizza
{
public Pizza(int slices)
{
Slices = slices;
}
public int Slices { get; set; }
}
class Program
{
static void Main(string[] args)
{
Pizza pizza1 = new Pizza(1);
Pizza pizza2 = new Pizza(1);
bool equal = AreEqual(pizza1, pizza2, new PizzaComparer());
Console.WriteLine(equal);
}
public static bool AreEqual<T>(T field, T value, IEqualityComparer<T> equalityComparer)
{
return equalityComparer.Equals(field, value);
}
}
public class Pizza
{
public Pizza(int slices)
{
Slices = slices;
}
public int Slices { get; set; }
}
public class PizzaComparer : IEqualityComparer<Pizza>
{
public bool Equals(Pizza pizza1, Pizza pizza2)
{
return pizza1.Slices == pizza2.Slices;
}
public int GetHashCode(Pizza pizza)
{
return pizza.Slices.GetHashCode();
}
}