Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[c#] Force upcast

Pagina: 1
Acties:

  • IStealYourGun
  • Registratie: November 2003
  • Laatst online: 16-10 21:36

IStealYourGun

Доверяй, но проверяй

Topicstarter
Ik heb volgend voorbeeld app gemaakt:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Point p1 = new Point(1, 2);

            TestPoint tp = new TestPoint(1,2);

            Point p2 = tp;

            Test(p1, p2);

        }

        static public void Test(Point p1, Point p2)
        {
            p1.Equals(p2);
        }
    }

    class Point
    {
        public Point(int x, int y)
        {
            X = x;
            Y = y;
        }

        public int X { get; set; }
        public int Y { get; set; }

        public override bool Equals(object obj)
        {
            if (obj == null) return false;
            if (obj.GetType() != typeof(Point)) return false;
            Point pt = (Point)obj;
            if (pt.X != this.X) return false;
            if (pt.Y != this.Y) return false;
            return true;
        }
    }

    class TestPoint : Point
    {
        public TestPoint(int x, int y) : base(x, y) { }
        public string name { get; set; }
    }
}


Nu, wanneer je p1.Equals(p2); aanroept dan returns deze false omdat de object types niet overeenstemmen. Dit klopt ergens wel, maar ergens ook niet.

Ik heb het in mijn project voorlopig opgelost met
C#:
1
if (obj is Point == false) return false;


Maar ik vroeg me af of dit wel de best practice is om met down en upcasting om te gaan?

♥ Under Construction ♦ © 1985 - 2013 and counting. ♣ Born to be Root ★ In the end, we are all communists ♠ Please, don't feed me meat


  • analog_
  • Registratie: Januari 2004
  • Niet online
if(true == true == true == true)

  • bwerg
  • Registratie: Januari 2009
  • Niet online

bwerg

Internettrol

Op de msdn-site wordt deze situatie met points toevallig als voorbeeld voor de Equals-methode gebruikt, dus doe er je voordeel mee (al is de situatie met de base-class wel anders dus die is niet gelijk aan een object van de superklasse met gelijke X en Y).

(ik heb geen idee of het minder goed is om het type te checken en dan eventueel te downcasten, want daar is mij C# te slecht voor, maar het komt op hetzelfde neer en bijvoorbeeld in Java gaat het altijd zo)

[ Voor 12% gewijzigd door bwerg op 24-06-2013 07:50 ]

Heeft geen speciale krachten en is daar erg boos over.


  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 28-02 22:17
Je moet ook altijd GetHashCode implementeren als je equals implementeert.

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info


  • Spockz
  • Registratie: Augustus 2003
  • Laatst online: 19-11 13:44

Spockz

Live and Let Live

Er is ergens ook een methode zoals is die ook voor super-class relaties bekijkt. Daarmee zou je dit probleem kunnen oplossen. Goedemorgen is doet dus precies wat jij wilt.

C#:
1
2
3
4
5
if( ! (obj is Point) ) {
  return false;
}

return (obj.x == this.x && obj.y == this.y);


Daarnaast weet ik nog niet of het wel zo netjes is om de semantiek van de reeds bestaande Equals functie te veranderen. Standaard gedrag is dat de functie inderdaad bij verschillende types false teruggeeft. Het lijkt mij beter / netter om een aparte functie voor dit gedrag te definiëren.

[ Voor 16% gewijzigd door Spockz op 24-06-2013 09:06 ]

C'est le ton qui fait la musique. | Blog | @linkedin
R8 | 18-55 IS | 50mm 1.8 2 | 70-200 2.8 APO EX HSM | 85 1.8


  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
IStealYourGun schreef op maandag 24 juni 2013 @ 01:56:
Ik heb volgend voorbeeld app gemaakt:

[code=c#]
Maar ik vroeg me af of dit wel de best practice is om met down en upcasting om te gaan?
Maar klopt het wel dat ze gelijk zijn. Het zal niet voor niks zijn dat het een andere class is, dus waarom zouden ze dan wel equal zijn?

Kijk op zich is de oplossing die je hebt technisch prima, maar ik betwijfel of het wel wenselijk is dat twee verschillende classes equal zijn.

Is het niet logischer om een functie van EqualLocation o.i.d. te maken?

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • R4gnax
  • Registratie: Maart 2009
  • Laatst online: 06-09 17:51
Woy schreef op maandag 24 juni 2013 @ 09:33:
[...]

Maar klopt het wel dat ze gelijk zijn. Het zal niet voor niks zijn dat het een andere class is, dus waarom zouden ze dan wel equal zijn?

Kijk op zich is de oplossing die je hebt technisch prima, maar ik betwijfel of het wel wenselijk is dat twee verschillende classes equal zijn.

Is het niet logischer om een functie van EqualLocation o.i.d. te maken?
Object.Equals is bedoeld voor value equality. Voor reference equality heb je Object.ReferenceEquals. De == operator gebruikt standaard reference equality maar in het .NET framework is het niet ongewoon dat value types (structs) deze operator overloaden om ook value equality te gebruiken.

Ik kan me ergens indenken dat het nuttig is om gelijkheid van punten te definiëren als gelijkheid in coördinaten, maar ik heb heel sterk het idee dat afgeleide types punten maken om verschillende typen metadata (zoals een naam) te koppelen aan die punten, beter op een andere manier gedaan kan worden. Het is niet echt iets waar inheritance lekker mee werkt. Iets zegt me dat een generic en value equality op een non-generic interface dan beter werkt:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
public interface IPoint {
  public int X { get; }
  public int Y { get; }
}

public class Point<TMetadata> : IPoint, IEquatable<IPoint>
{
  public int X { get; private set; };
  public int Y { get; private set; };
  
  public TMetadata Metadata { get; private set; };
  public Type MetadataType { get { return typeof(TMetadata); }};
  
  public Point(int x, int y, TMetadata metadata)
  {
    X = x;
    Y = y;
    Metadata = metadata;
  }
  
  public bool Equals(IPoint other)
  {
    if (other == null) return;    
    return X == other.X && Y == other.Y;
  }
  
  public override bool Equals(object obj)
  {
    if (obj == null) return false;
    if (this == obj) return true;
    
    return Equals(obj as IPoint);
  }
  
  public override int GetHashCode()
  {
    unchecked // Numerical overflow is OK here.
    {
      int hash = 17;
      
      hash = hash * 23 + X.GetHashCode();
      hash = hash * 23 + Y.GetHashCode();
      
      return hash;
    }
  }
}

  • IStealYourGun
  • Registratie: November 2003
  • Laatst online: 16-10 21:36

IStealYourGun

Доверяй, но проверяй

Topicstarter
Woy schreef op maandag 24 juni 2013 @ 09:33:
[...]

Maar klopt het wel dat ze gelijk zijn. Het zal niet voor niks zijn dat het een andere class is, dus waarom zouden ze dan wel equal zijn?
Daar zit net een beetje mijn probleem. Als je kijkt naar het type van p2, dan is dit een TestPoint, ondanks dat p2 gedefinieerd is als een Point. Het ideale zou zijn dat tp wordt geupcast wanneer hij wordt toegewezen aan p2.
Woy schreef op maandag 24 juni 2013 @ 09:33:
[...]
Is het niet logischer om een functie van EqualLocation o.i.d. te maken?
Ik zie niet echt in waarom, de class bevat 2 variabelen en het lijkt me logisch dat je daarmee vergelijkt. Overal in mijn programma is dat zelfs de voorwaarde, ik kom enkel in de problemen bij het Type van de class.
Grijze Vos schreef op maandag 24 juni 2013 @ 08:49:
Je moet ook altijd GetHashCode implementeren als je equals implementeert.
Weet ik, maar dat is irrelevant in dit voorbeeld.
bwerg schreef op maandag 24 juni 2013 @ 07:47:
Op de msdn-site wordt deze situatie met points toevallig als voorbeeld voor de Equals-methode gebruikt, dus doe er je voordeel mee (al is de situatie met de base-class wel anders dus die is niet gelijk aan een object van de superklasse met gelijke X en Y).
Is een beetje gelijkaardig aan wat ik doe en zal bij mij ook wel werken, alleen is het strikt gezien wel fout aan gezien p2 van het type Testpoint is, ondanks dat het gedefinieerd is als Point.

♥ Under Construction ♦ © 1985 - 2013 and counting. ♣ Born to be Root ★ In the end, we are all communists ♠ Please, don't feed me meat


  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
IStealYourGun schreef op maandag 24 juni 2013 @ 11:28:
[...]
Daar zit net een beetje mijn probleem. Als je kijkt naar het type van p2, dan is dit een TestPoint, ondanks dat p2 gedefinieerd is als een Point. Het ideale zou zijn dat tp wordt geupcast wanneer hij wordt toegewezen aan p2.
Hier ben ik je even kwijt, ook al wijs je tp toe aan p2, het is en blijft nog steeds van het type TestPoint, waarom zou die gelijk zijn aan iets van het type Point? Als ze echt gelijk zouden zijn, zouden ze immers ook hetzelfde type hebben.
Ik zie niet echt in waarom, de class bevat 2 variabelen en het lijkt me logisch dat je daarmee vergelijkt. Overal in mijn programma is dat zelfs de voorwaarde, ik kom enkel in de problemen bij het Type van de class.
Dat de data gelijk is zegt nog niet dat ze helemaal gelijk zijn natuurlijk. Ze zijn van een verschillend type, en TestPoint heeft meer parameters die Point helemaal niet heeft, dus dat lijkt me reden genoeg om ze als ongelijk te beschouwen.
Weet ik, maar dat is irrelevant in dit voorbeeld.
Niet helemaal. Als equals true oplevert zou de hash ook gelijk moeten zijn, dat lijkt me niet helemaal wenselijk, want ze zijn niet exact gelijk aan elkaar. Zo te zien wil je van twee types alleen de coordinaten vergelijken en niet het hele object.
R4gnax schreef op maandag 24 juni 2013 @ 11:19:
[...]
Object.Equals is bedoeld voor value equality. Voor reference equality heb je Object.ReferenceEquals. De == operator gebruikt standaard reference equality maar in het .NET framework is het niet ongewoon dat value types (structs) deze operator overloaden om ook value equality te gebruiken.
Klopt, maar value equality is logischerwijs ook niet van toepassing omdat het verschillende types zijn ( Waar 1 van de types ook nog meer data heeft )

[ Voor 16% gewijzigd door Woy op 24-06-2013 11:54 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • IStealYourGun
  • Registratie: November 2003
  • Laatst online: 16-10 21:36

IStealYourGun

Доверяй, но проверяй

Topicstarter
Woy schreef op maandag 24 juni 2013 @ 11:53:
[...]

Hier ben ik je even kwijt, ook al wijs je tp toe aan p2, het is en blijft nog steeds van het type TestPoint, waarom zou die gelijk zijn aan iets van het type Point? Als ze echt gelijk zouden zijn, zouden ze immers ook hetzelfde type hebben.
True, maar je zou kunnen verwachten dat hierna:
C#:
1
Point p2 = tp;


Alle overbodige informatie van Testpoint wordt weggegooid en p2 en "pure" Point is en niet een Testpoint.

♥ Under Construction ♦ © 1985 - 2013 and counting. ♣ Born to be Root ★ In the end, we are all communists ♠ Please, don't feed me meat


  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
IStealYourGun schreef op maandag 24 juni 2013 @ 12:14:
[...]


True, maar je zou kunnen verwachten dat hierna:
C#:
1
Point p2 = tp;


Alle overbodige informatie van Testpoint wordt weggegooid en p2 en "pure" Point is en niet een Testpoint.
Je bedoelt een beetje zoals C++ zou doen :+ ( Met object slicing tot gevolg ).

Maar dat lijkt me niet wenselijk. Als je dat zou willen doen moet je gewoon een expliciete conversie (operator) schrijven. Je wil gewoon niet dat bij een assignment het type daadwerkelijk veranderd. Al lijkt een conversie operator naar een baseclass me ook erg verwarrend.

[ Voor 12% gewijzigd door Woy op 24-06-2013 12:19 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • IStealYourGun
  • Registratie: November 2003
  • Laatst online: 16-10 21:36

IStealYourGun

Доверяй, но проверяй

Topicstarter
Woy schreef op maandag 24 juni 2013 @ 12:16:
[...]

Je bedoelt een beetje zoals C++ zou doen :+ ( Met object slicing tot gevolg ).
Shit, ik heb gewoon de verkeerde taal gekozen
Maar dat lijkt me niet wenselijk. Als je dat zou willen doen moet je gewoon een expliciete conversie (operator) schrijven. Je wil gewoon niet dat bij een assignment het type daadwerkelijk veranderd. Al lijkt een conversie operator naar een baseclass me ook erg verwarrend.
Stof voor discussie, voor mij lijkt dit logischer dat het type dan wel veranderd en dat er, of een fout optreed omdat types niet overeenstemmen, of een upcasting gebeurt. Nu goed, c# (of .net) doet dit niet, vraag is alleen, hoe vang ik dit in deze situatie best op?

♥ Under Construction ♦ © 1985 - 2013 and counting. ♣ Born to be Root ★ In the end, we are all communists ♠ Please, don't feed me meat


  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
IStealYourGun schreef op maandag 24 juni 2013 @ 12:31:
[...]

Shit, ik heb gewoon de verkeerde taal gekozen
Ook daar is het niet zondermeer aan te raden ;)
Stof voor discussie, voor mij lijkt dit logischer dat het type dan wel veranderd en dat er, of een fout optreed omdat types niet overeenstemmen
Dan haal je het hele principe van polymorphisme onderuit.
, of een upcasting gebeurt.
Casting is in feite niet meer dan een compiler aangelegenheid, en veranderd niet daadwerkelijk wat aan het type.
Nu goed, c# (of .net) doet dit niet, vraag is alleen, hoe vang ik dit in deze situatie best op?
Als je echt wil dat het type veranderd zal je een Conversie moeten doen. Maak bijvoorbeeld een methode "Point ToPlainPoint()" die een nieuw point terug geeft.

Als je bijvoorbeeld een class Auto hebt met de subclasses Renault en Porsche, waar de auto het attribuut "Kleur" heeft, dan wil je toch ook niet dat een rode Renault gelijk staat aan een rode Porsche? Hooguit zou je een method CompareColor willen hebben.

Overigens is er natuurlijk geen technische beperking om het zo te doen zoals jij wil, maar het lijkt me semantisch niet correct.

[ Voor 5% gewijzigd door Woy op 24-06-2013 12:37 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • IStealYourGun
  • Registratie: November 2003
  • Laatst online: 16-10 21:36

IStealYourGun

Доверяй, но проверяй

Topicstarter
Woy schreef op maandag 24 juni 2013 @ 12:36:
Als je bijvoorbeeld een class Auto hebt met de subclasses Renault en Porsche, waar de auto het attribuut "Kleur" heeft, dan wil je toch ook niet dat een rode Renault gelijk staat aan een rode Porsche? Hooguit zou je een method CompareColor willen hebben.
Zoals ik al zei, voer tot discussie. Als ik naar een garage ga en aan de verkoper vraag om mij een rode Porsche te tonen, dan verwacht ik een rode Porsche en niet een rode Renault.

Maar als ik vraag naar een rode wagen, dan maakt het merk voor mij niet meer uit. Laten we er even van uitgaan dat onze garagist autistisch is en ik binnenkom met de vraag: "Ik kom mijn rode wagen ophalen die ik gisteren heb binnengebracht." In principe voldoen de rode Porsche en de rode Renault aan die voorwaarde en met een beetje geluk geeft hij mij de Porsche. ;) En dit is toch wat hier een beetje gebeurt. Dat dit misschien van het type TestPoint is geweest kan goed zijn, maar vanaf p2 boeit mij dat niet want ik definieer een Point en niet een TestPoint.

Ik snap weliswaar vanwaar het allemaal komt, de manier van werken die c# toepast zorgt voor meer flexibiliteit en de toepassing is in zekere zin oké, maar kan ook voor problemen geven zoals bij mij of:
C#:
1
2
3
4
5
6
7
8
9
10
tp1.name = "Een punt";

Point p2 = tp1; //Vanaf nu heeft p2 geen variable "name". 

TestPoint tp2 = p2; // Geeft een fout, ondanks p2.gettype == Testpoint :/

TestPoint tp3 = (TestPoint)p2; //lukt wel, maar niet zo veilig

object o = new object();
TestPoint tp4 = (TestPoint)o; // < ik bedoel maar...


Dus in sommige gevallen, zoals bij mij, is die flexibiliteit niet wenselijk. Mijn vraag is nu hoe ik hier best mee omga. Bestaat er geen keyword dat bij het definiëren de exacte types afdwingt? Een soort van:

C#:
1
2
"magic keyword" Point p2 = tp1; //Geeft fout
"magic keyword" Point p3 = new Point(tp1.X, tp1.Y); //Of een Testpoint.CastToPoint();


Kwestie van mijn code idiot-proof te maken.

♥ Under Construction ♦ © 1985 - 2013 and counting. ♣ Born to be Root ★ In the end, we are all communists ♠ Please, don't feed me meat


  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
IStealYourGun schreef op maandag 24 juni 2013 @ 14:01:
[...]
Maar als ik vraag naar een rode wagen, dan maakt het merk voor mij niet meer uit. Laten we er even van uitgaan dat onze garagist autistisch is en ik binnenkom met de vraag: "Ik kom mijn rode wagen ophalen die ik gisteren heb binnengebracht." In principe voldoen de rode Porsche en de rode Renault aan die voorwaarde en met een beetje geluk geeft hij mij de Porsche. ;) En dit is toch wat hier een beetje gebeurt. Dat dit misschien van het type TestPoint is geweest kan goed zijn, maar vanaf p2 boeit mij dat niet want ik definieer een Point en niet een TestPoint.
Maar dan heb je het over een filter/predicate, en niet over gelijkheid. Beide auto's voldoen aan het predikaat van "auto => auto.Kleur == Rood", maar dat maakt ze nog niet gelijk.
Ik snap weliswaar vanwaar het allemaal komt, de manier van werken die c# toepast zorgt voor meer flexibiliteit en de toepassing is in zekere zin oké, maar kan ook voor problemen geven zoals bij mij of:
C#:
1
2
3
4
5
6
7
8
9
10
tp1.name = "Een punt";

Point p2 = tp1; //Vanaf nu heeft p2 geen variable "name". 

TestPoint tp2 = p2; // Geeft een fout, ondanks p2.gettype == Testpoint :/

TestPoint tp3 = (TestPoint)p2; //lukt wel, maar niet zo veilig

object o = new object();
TestPoint tp4 = (TestPoint)o; // < ik bedoel maar...
Je moet goed begrijpen dat casten puur een compiler aangelegenheid is, en dat het geen enkele aanpassing aan het type maakt. Het feit dat een referentie van het type Auto ook een Porsche of Renault kan bevatten is essentieel voor polymorphisme.
Dus in sommige gevallen, zoals bij mij, is die flexibiliteit niet wenselijk. Mijn vraag is nu hoe ik hier best mee omga. Bestaat er geen keyword dat bij het definiëren de exacte types afdwingt? Een soort van:

C#:
1
2
"magic keyword" Point p2 = tp1; //Geeft fout
"magic keyword" Point p3 = new Point(tp1.X, tp1.Y); //Of een Testpoint.CastToPoint();


Kwestie van mijn code idiot-proof te maken.
Je wil IMHO nooit dat je automatisch gaat converteren, want de "Naam" property in je voorbeeld zou zo maar eens essentiele informatie voor dat type kunnen zijn. Sowieso is het Type al essentiele informatie voor gelijkheid. Casten is geen transformatie, het is puur een indicatie voor de compiler. Als je echt wil transformeren moet je dat expliciet doen, en dat levert een nieuw object op.

Om terug te gaan naar het Auto voorbeeld. De Porsche zal nooit gelijk zijn aan de Renault, maar het kan best zijn dat ze beide voldoen aan het criteria IsRood. Anders zou een Rode voetbal ook gelijk kunnen zijn aan een Porsche :?

[ Voor 4% gewijzigd door Woy op 24-06-2013 15:23 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • R4gnax
  • Registratie: Maart 2009
  • Laatst online: 06-09 17:51
IStealYourGun schreef op maandag 24 juni 2013 @ 12:31:
Stof voor discussie, voor mij lijkt dit logischer dat het type dan wel veranderd en dat er, of een fout optreed omdat types niet overeenstemmen, of een upcasting gebeurt. Nu goed, c# (of .net) doet dit niet, vraag is alleen, hoe vang ik dit in deze situatie best op?
Via de voorbeeldcode die ik je al gegeven heb: een IPoint interface gepaard met een IEquatable<IPoint> interface. Beiden implementeren op een class om ze 'als punt' te kunnen vergelijken en de basis Equals(object) implementatie op deze classes worden naar de Equals(IPoint) implementatie doorgelust met een een reference converison naar IPoint. Een reference conversion via de 'as' operator geeft gewoon null terug als een object niet te converteren is en dat zal in de Equals(IPoint) implementatie meteen falen.

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
R4gnax schreef op dinsdag 25 juni 2013 @ 18:56:
[...]


Via de voorbeeldcode die ik je al gegeven heb: een IPoint interface gepaard met een IEquatable<IPoint> interface. Beiden implementeren op een class om ze 'als punt' te kunnen vergelijken en de basis Equals(object) implementatie op deze classes worden naar de Equals(IPoint) implementatie doorgelust met een een reference converison naar IPoint. Een reference conversion via de 'as' operator geeft gewoon null terug als een object niet te converteren is en dat zal in de Equals(IPoint) implementatie meteen falen.
Semantisch gezien zou het IMHO dan logischer zijn om IComparable<IPoint> te implementeren. Overigens voegt de IEquatable<IPoint> in jouw geval niet zo heel veel toe want je Equals(object) methode controleert ook al niet op Type ;).

Het ligt een beetje aan het doel van de TS hoe ik het op zou lossen, maar in plaats van de generieke interfaces te gebruiken die eigenlijk voor objecten van hetzelfde type bedoeld zijn zou ik eerder gewoon een extra interface of methode toevoegen.

C#:
1
2
3
4
public interface ILocationComparer
{
    bool HasEqualLocation( IObjectWithLocation obj );
}


o.i.d.

[ Voor 17% gewijzigd door Woy op 25-06-2013 19:20 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • R4gnax
  • Registratie: Maart 2009
  • Laatst online: 06-09 17:51
Woy schreef op dinsdag 25 juni 2013 @ 19:15:
Semantisch gezien zou het IMHO dan logischer zijn om IComparable<IPoint> te implementeren. Overigens voegt de IEquatable<IPoint> in jouw geval niet zo heel veel toe want je Equals(object) methode controleert ook al niet op Type ;).
Semantisch ben je bezig te kijken of twee punten equivalent zijn, waar de IEquatable<T> interface voor bedoeld is. Je bent niet bezig te kijken of het ene punt 'groter' is dan het andere, waar de IComparable<T> interface voor bedoeld is.

De standaard Object.Equals(object) aanroep legt het type niet expliciet vast. Het implementeren van IEquatable<IPoint> voegt een strongly-typed overload toe waarmee dit wel gebeurt. In dat opzicht heeft het zeker toegevoegde waarde. De standaard implementatie in Object.Equals(object) is overigens reference equality en dat is ook wat mijn implementatie doet voor objecten die IPoint niet implementeren. Lijkt me gewoon correct...
Woy schreef op dinsdag 25 juni 2013 @ 19:15:
Het ligt een beetje aan het doel van de TS hoe ik het op zou lossen, maar in plaats van de generieke interfaces te gebruiken die eigenlijk voor objecten van hetzelfde type bedoeld zijn zou ik eerder gewoon een extra interface of methode toevoegen.
Volg dan het .NET framework en definieer een externe comparer class die IEqualityComparer<T> implementeert:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
public class PointEqualityComparer : IEqualityComparer<IPoint>
{
    public bool Equals(IPoint first, IPoint second)
    {
        // ...
    }

    public int GetHashCode(IPoint point)
    {
        // ...
    }
}

Moet je wel overal expliciet van deze comparer gebruik maken.
Pagina: 1