Avatar billede screwdriver Nybegynder
15. september 2011 - 09:41 Der er 8 kommentarer og
1 løsning

Interface: Kræv at en metodes parameter er samme type som klassen

Jeg vil gerne lave et interface, indeholdende en metode som kan kopiere indholdet af parametret til klassen.
Det kræver selvfølgelig at parametret er af samme type som selve klassen

Jeg har for søgt med dette, men den går ikke

    interface ICopyAble
    {
        void CopyFrom(typeof(this) Source );
    }

Nogen der ved, hvordan man angiver at parametret skal være klassens type?

Jeg forventer at bruge den således:

public class MyClass : ICopyAble
{

  // Properties
  public int Data {get;set;}

  public void CopyFrom (MyClass Source)
  {
    // Copy Data
    this.Data = Source.Data;
    // More data later
  }
}
Avatar billede heinzdmx Nybegynder
15. september 2011 - 09:50 #1
Synes da umiddelbart det lyder som ICloneable

http://msdn.microsoft.com/en-us/library/system.icloneable.aspx
Avatar billede Syska Mester
15. september 2011 - 09:51 #2
Generics:

public interface ICopyAble
    {
        T CopyFrom<T>(T inputItem);
    }

Alternativt ... alt efter hvordan du synes det er pænæst.

public interface ICopyAble<T>
    {
        T CopyFrom(T inputItem);
    }

Som så vil komme til at se sådan her ud:
public class MyClass : ICopyAble<string>
    {
        public string CopyFrom(string inputItem)
        {
            throw new System.NotImplementedException();
        }
    }
Avatar billede screwdriver Nybegynder
15. september 2011 - 10:51 #3
heinzdmx:
ICloneable.Clone retunerer et nyt objekt. Det jeg ønsker er at kopiere data ind i et eksisterende objekt.

buzzzz:
Det kan man selvfølgelig gøre, men det jeg vil er:

MyClass c1 = new MyClass ();
MyClass c2 = new MyClass ();

...

c1.CopyFrom (c2) ;

...

På din måde skal man angive klassen i definitionen af klassen:
public class MyClass : ICopyAble<MyClass>

og kan dermed angive en forkert:
public class MyClass : ICopyAble<MyClass2>

Min ide var at Interfacet skulle kræve at parametret var samme type som klassen (som her - hvis det havde virket):
interface ICopyAble<T> where T : typeof(this)
{
  void CopyFrom(T Source );
}
Avatar billede Syska Mester
15. september 2011 - 11:27 #4
Virker som om du prøver at løse et problem jeg ikke lige kan gennemskue.
Avatar billede skelboe Nybegynder
16. september 2011 - 12:05 #5
Hvis det er for at typen kan tilpasses, kan du vel skrive dit interface såden her

interface ICopyAble
{
        void CopyFrom(object Source );
}

og når du implementer data

class MyClass : ICopyAble
{
    public void CopyFrom(object Source)
    {
        MyClass src = Source as MyClass;

        if (src != null)
        {
            // TODO: Copy data
        }
        else
        {
            throw new Exception("Wrong type");
        }
    }
}
Avatar billede bvli Praktikant
16. september 2011 - 12:58 #6
Jeg tror godt jeg forstår dit problem. Og der er ikke en constraint på generics du kan bruge. Men jeg tror faktisk at din tilgang til det er lidt bagvendt.

Hvis du alligevel vil have at metoden skal "overskrive" din eksisterende instans, hvorfor så ikke lade den returnere den i stedet?

MyClass c1 = new MyClass();
[...]

MyClass c2 = c1.Copy();

Dermed undgår du også, at du kan skrive en "forkert" type i din generic.
Avatar billede screwdriver Nybegynder
21. september 2011 - 15:45 #7
skelboe:
Du har ret i at man kan gøre det du angiver, men det vil give en fejl ved runtime, hvis man kalder den med et forkert objekt.
Det jeg ønsker er at interfacet kræver at typen man kalder objektet med er det samme som objektet.

bvli:
Det jeg ønsker er at overskrive data.
Mit c1 har nogle events, som andre objekter abonerer på. Så kommer der et nyt objekt (c2 )som indeholder nye data. Dem vil jeg gerne have have over i c1, som så samtidig raiser et event om at der er nye data. Den information skal så komme til de objekter, som abonerer på c1.

Alt det er ikke svært at lave, men jeg ønsker at lave et interface, som kræver dette, således at jeg bare kan implementere ICopyable, og så er jeg sikker på at klassen er korrekt
Avatar billede Syska Mester
21. september 2011 - 16:16 #8
#screwdriver
Jeg er på ingen måder uber ekspert.

Hvis man endelig kunne, så tror jeg også at .NET selv ville have valgt at gøre det med: IEqualityComparer<string>, IEquatable<>, og mange flere ...

Men hvis du alligevel skal huske at implementere et interface ... for at bruge en method og ikke selv interfacet er der så ikke noget galt i din akitektur?

Som jeg har kunnet google mig til, har java noget der hedder "self bounding generics" som måske er det du leder efter. Blev ikke helt klog på det ... da de også snakkede om Scala.

Generics handler i min verden om at behandle ting på samme måde.

Du vil reelt bare her have en metode på din klasse som hedder "Copy" som bare tager et item. Er det ikke ligeså nemt at implementere og huske at gøre det hvis der alligevel ikke bliver brugt generics ?

Det eneste du kan er en smide en masse constraints på dit interface eller.

Eventuelt kan du kigge på PostSharp som kan lave en masse compile time check om klasser der implementere interface I har en metoder der hedder copy som tager en parameter af sig selv.

mvh
Avatar billede screwdriver Nybegynder
18. oktober 2011 - 09:34 #9
Jeg endte med at gøre følgende:

    public interface ICopyable<T>
    {
        void CopyFrom(T Source);
    }

Jeg ville gerne have lavet en begrænsning på T, som sagde at den skulle være this (eller en klasse der arvede fra this), men konklusionen må være at det ikke (Umuddelbart) kan lade sig gøre.

Jeg lukker derfor spørgsmålet
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester