简体   繁体   中英

C# Comparing a reference and a value

I have trouble with this method when passing values to it.

Notice: The system using this function is from my perspective a black box and can therefore not be changed.

The problem is that passing identical values such as strings, bools, objects etc. to the method will say that they are not equal even though the values are identical. I assumed that it is because one is a reference while the other is a value and they therefore "are different".

    protected void SetData<T>(ref T field, T value)
        {
            if (!EqualityComparer<T>.Default.Equals(field, value))
            {
                Console.WriteLine("They are NOT equal");
            }
            else
            {
                Console.WriteLine("They are equal");
            }
        }

To test this assumption I made some different unit tests.

        public bool AreEqual<T>(ref T field, T value)
        {
            return EqualityComparer<T>.Default.Equals(field, value);
        }

    [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);
    }

The result is that the unit tests all pass... as "expected"

So when I test, it works as intended, but when I connect to the rest of the system and debug so i can see the values of "field" and "value", it does not.

Has anybody tried something like this before?

You are missing the equality comparer.

As you can see in this example even if equals, the output will be 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; }
}

Output:

False


This way it will work even with custom objects:

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();
    }
}

Output:

True

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM