Stránka 1 z 1

[C#] porovnání listů s objekty

Odeslat příspěvekNapsal: 8. 12. 2016 03:50
od milanc
Ahoj,

začínám s C# a potřebuji poradit. Mám nějaký List FuzzySet naplněný vlastními objekty - FuzzyElement.
Ve třídě Fuzzy element již mám implementaci IComparable pro porovnání dvou prvků.

Nyní se ale snažím porovnat dva Listy těchto objektů v rámci unit testu.

Pro rovnost to zkouším takto, ale jestli nemám chybu jinde, tak to nefunguje.
if (this.Count == other.Count && this.SequenceEqual(other))

Pak jsem zkoušel toto, ale také mi to vyhodnotí dvě stejné množiny jako nerovné.
if (this.Count == other.Count && this.SequenceEqual<FuzzyElement>(other))

Obecně mám trochu problém s tím, že nevím, jak ladit ty unit testy.
Jaký je přesně rozdíl mezi uvedenými příkazy, resp. jak to porovnává ten první? Ten druhý předpokládám využívá právě CompareTo?

Kód je zde: http://www.cizekmilan.cz/FuzzySet.zip
Děkuji za pomoc.

Re: [C#] porovnání listů s objekty

Odeslat příspěvekNapsal: 8. 12. 2016 07:45
od Nargon
IComparable se používá pro řazení, protože to poskytuje 3 stavy: -1,0,1 jednotlivé stavy odlišují zda jsou objekty stejné (0) a nebo zda je jeden větší/menší (1 a -1)
Ale pro obyčejné porovnání "stejnosti" (hrozný slovo co) se většinou používají metody GetHashCode: https://msdn.microsoft.com/en-us/librar ... hcode.aspx a Equals: https://msdn.microsoft.com/en-us/library/bsc2ak47.aspx takže ještě implementovat tyhle dvě metody a mělo by to začít porovnávat správně.

Ale jak to ladit, nebo jak je implementovaný ten jeden a ten druhý fakt nevím.

Re: [C#] porovnání listů s objekty

Odeslat příspěvekNapsal: 8. 12. 2016 09:32
od pucmeloudek
krome toho, ze predseda ma pravdu (aneb zdurazneno: to, ze IComparable vraci 0, v zadnem pripade neznamena, ze jsou objekty stejne, jen to, ze jsou z hlediska razeni rovnocenne), tak rozdil mezi zapisy sequenceequal je pouze ten, ze v prvnim pripade si usetris trochu psani. mj. to poznas podle toho, ze novejsi verze visual studia ten zbytecny kus kodu udelaj takovej min vyraznej. uplatnuje se tam tzv. type inference, prekladac ti prislusny parametr generika sam domysli podle predaneho parametru.

Re: [C#] porovnání listů s objekty

Odeslat příspěvekNapsal: 9. 12. 2016 04:53
od milanc
Ahoj,

pokusil jsem se jako první upravit FuzzyElement. Přetížil jsem i == a !=, protože jestli správně chápu je to třeba, protože == používám v Equals. Nicméně mi to stále nefunguje. Pokud pomocí Equals porovnám dva prvky (různé objekty) se stejným Value i Grade, vrací mi chybně false.

Kód: Vybrat vše
using System;
using System.Globalization;

namespace Fuzzy
{
    [System.Diagnostics.DebuggerDisplay("\\{ Value = {X}, Grade = {Y} \\}")]
    public class FuzzyElement : IComparable<FuzzyElement>
    {
        public object Value { get; private set; }
        public double Grade { get; private set; }

        public FuzzyElement(object Value, double Grade)
        {
            this.Value = Value;
            this.Grade = Grade;
        }


        public override bool Equals(object obj)
        {
            if (obj == null)
            {
                return false;
            }
            var other = obj as FuzzyElement;
            if ((object)other == null)
            {
                return false;
            }
            return this == other;
        }

        public bool Equals(FuzzyElement other)
        {
            if ((object)other == null)
            {
                return false;
            }
            return this == other;
        }

        public override int GetHashCode()
        {
            return this.Value.GetHashCode() ^ this.Grade.GetHashCode();
        }

        public static bool operator ==(FuzzyElement left, FuzzyElement right)
        {
            if (object.ReferenceEquals(left, right))
            {
                return true;
            }
            if ((object)left == null || (object)right == null)
            {
                return false;
            }
            return left.Value == right.Value && left.Grade == right.Grade;
        }

        public static bool operator !=(FuzzyElement left, FuzzyElement right)
        {
            return !(left == right);
        }

        public int CompareTo(FuzzyElement other)
        {
            if (!this.Value.Equals(other.Value))
                return -1;
            else
            {
                if (this.Grade < other.Grade)
                    return -1;
                else if (this.Grade > other.Grade)
                    return 1;
                else
                    return 0;
            }
        }

        public override string ToString()
        {
            // CultureInfo jen kuli tomu, že chci mít jako oddělovač desetinných míst "."
            return Grade.ToString(CultureInfo.CreateSpecificCulture("en-GB")) + "/" + Value.ToString();
        }

    }
}


Unit test
Kód: Vybrat vše
            FuzzyElement E4 = new FuzzyElement(5, 0.9);
            FuzzyElement E5 = new FuzzyElement(5, 0.9);

            // E4=E5, 5=5, 0.9=0.9 (stejné prvky, stejné stupně)
            Expected = true;
            Result = E4.Equals(E5);
             Assert.AreEqual(Expected, Result, String.Format("Porovnání-5 {0} = {1} -> {2}.",
                E4.ToString(), E5.ToString(), Result));


Když testuju E4 == E5, tak vrací false. Ale prostě nevidím v té metodě nic špatně.

Re: [C#] porovnání listů s objekty

Odeslat příspěvekNapsal: 9. 12. 2016 06:34
od Nargon
Doporučuji naučit se používat debugger a krokovat si jednotlivé části. Pak by jsi přišel na to samé co já.
False ti to vrací z důvodu podmínky u operátoru ==, tam je problém s tím porovnáním left.Value == right.Value.
Protože proměnná "Value" je typu object tak se zde neporovnává obsah ale pouze reference a ta každá ukazuje na jiný objekt takže vrátí false.
Kdyby jsi měl proměnou Value definovanou jako int tak ti to bude fungovat, protože u intů se operátorem == porovnává jejich hodnota, nikoli reference jako u object.

Re: [C#] porovnání listů s objekty

Odeslat příspěvekNapsal: 22. 12. 2016 17:19
od rudidlo
Stačí implementovat IEquatable<T>, přepsat negenerickou metodu Equals(object o) a GetHashCode, jak píše Nargon a objekty pak porovnávat přes objectA.Equals(objectB)

Re: [C#] porovnání listů s objekty

Odeslat příspěvekNapsal: 22. 12. 2016 17:44
od satikcz
Ještě dodám, že na testování kolekcí bys měl ideálně používat CollectionAssert:

https://msdn.microsoft.com/en-us/librar ... ssert.aspx