Fragen zu Interfaces in c#

  • C#
  • .NET 9

Es gibt 9 Antworten in diesem Thema. Der letzte Beitrag () ist von siycah.

    Fragen zu Interfaces in c#

    Neu

    Hallo,

    bei Interfaces in c# bemerke ich gerade einige Besonderheiten im Vergleich zu vb. Ich hätte da eine Sammlung an Fragen.

    Erstmal hab ich mich eingelesen, da bin ich auf eine Diskrepanz gestoßen. Microsoft schreibt
    Interface members without an implementation can't include an access modifier. Members with a default implementation can include any access modifier.
    Das geht aber, und mit internal oder protected auch,

    C#-Quellcode

    1. public interface ITest
    2. {
    3. public int A(); //internal, protected auch
    4. }
    bei private muss ich eine Default-Implementierung vornehmen, da stimmts. Vielleicht ist das auch schon wieder veraltet, das ist ja wohl noch gar nicht so lange her, dass das eingeführt wurde.
    Hinterher implementieren kann ich es nicht mit internal oder protected dann, also teilweise stimmt es dann doch?

    Da komme ich dann zur zweiten Frage. Das Studio schlägt bei Angabe des Interfaces in einer Klasse vor "Schnittstelle implementieren" und "Alle member explizit implementieren"
    Bei letzterem fehlt der access modifier, und es wird die Schnittstelle vorangestellt, was hat es damit auf sich?

    C#-Quellcode

    1. public class Class1 : ITest
    2. {
    3. int ITest.A()
    4. {
    5. throw new NotImplementedException();
    6. }
    7. }
    Wenn ich an einem Interface internal oder protected definiere wird auch nur der zweite Vorschlag gemacht (also dieser Code ^).

    Und als Drittes gehts um die Default-Implementierung. Funktionert das genauso wie ein virtual Member in einer base class + override in der derived class oder gibt es da Besonderheiten?

    Viele Grüße

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Haudruferzappeltnoch“ ()

    Neu

    Deine erste Frage verstehe ich nicht ganz. Wenn du eine Standardimplementierung im Interface hat, kann die Funktion jegliche Zugriffsmodifizierer haben. Dein Beispiel hat keine Standardimplementierung.

    Eine Klasse kann mehrere Interfaces implementieren. Sollten zwei oder mehrere Interfaces die selbe Funktionsdefinition haben, kannst du mit der expliziten Implementierung die Herkünfte unterscheiden.

    C#-Quellcode

    1. ​internal class FooBar : IFoo, IBar
    2. {
    3. void IBar.Bar()
    4. {
    5. throw new NotImplementedException();
    6. }
    7. void IFoo.Bar()
    8. {
    9. throw new NotImplementedException();
    10. }
    11. void IFoo.Foo()
    12. {
    13. throw new NotImplementedException();
    14. }
    15. }


    Die Standardimplementierung funktioniert ähnlich einer Basisklasse mit override. Nur dass man keine "Basisklasse" benötigt.

    Neu

    Seit C# 8 kann man in Interfaces Methoden mit Inhalt schreiben.
    Viele C#-Entwickler finden das nicht gut, weil Interfaces eigentlich nur Verträge sein sollten.
    Ob man Default-Methoden nutzt, ist Geschmackssache.
    Manche neigen dazu ganze Logik rein zu schreiben.
    Ich lass das lieber weg.

    Neu

    Interfaces kann man als Blaupause für eine Klasse sehen. Es ergibt hier keinen Sinn, private Funktionen ohne Body zu deklarieren. Protected geht, weil diese auch in geerbten Klassen sichtbar sind - und daher meckert VS das nicht an.
    Wie gesagt, in Interfaces sind alle Deklarationen implizit public, in Klassen private. Daher auch das automatische hinzufügen des public-Schlüsselwortes, wenn die Schnittstelle automatisch implementiert wird.

    Neu

    Ich würde auch gerne meinen Senf dazu abgeben wollen.

    Wenn ich Azubis und neuen Programmierern Vererbung beibringe, dann verwende ich - v.a. bei Sprachen die all diese Konstrukte haben - folgende Analogie:

    Du bist der Architekt und Bauherr, der Compiler ist der Bautrupp, der deinen Anweisungen folge zu leisten hat.

    Interface: Ein Interface ist die Musterzeichnung des Gebäudes. Hier werden nur die abstrakten Eigenschaften aufgelistet. Jedes Gebäude von diesem Typ muss diese Eigenschaften irgendwie implementieren.
    Beispiel: Ein Bungalow wird immer nur ein Erdgeschoss (überirdisch) haben.
    Eigenschaften können jedoch hinzugefügt werden: bspw. können Bungalows eine Garage bekommen.
    Es ist die unterste Vertragsebene: Hierüber sind sich alle Parteien einig.

    Abstrakte Klasse (C++ = pure virtual class): Um bei meiner Analogie zu bleiben, ist die abstrakte Klasse die Zeichnung vom Architekten, die das Bauamt bekommt.
    Hier definierst du nicht nur grundlegende Eigenschaften, sondern auch intrinsische Eigenschaften, die letztendlich aber noch überschrieben werden können.
    Z.B. definierst du hier, dass du im Erdgeschoss 8 IFenster hast - wobei hier entscheidend ist, dass du nur definierst, dass es Fenster sind, nicht welche Art Fenster (Butzenfenster, Milchglassfenster, etc.).
    Dein Haus ist nun grundsätzlich durchdefiniert, es es fehlt noch der Feinschliff, die Bemusterung, quasi.

    Klasse: Dein Haus. Die Klasse (class) ist dein Haus; du hast nun alle Entscheidungen und Schliffe getroffen, die das Haus nun zu deinem machen.
    Du hast durchdefiniert, welche Eigenschaften und Methoden dein Haus in welcher Form hat.
    Mit dieser vollendeten Basis kann nun der Bautrupp loslegen und den ersten Stein setzen.

    Was ganz wichtig ist: deine Klasse ist NICHT dein Objekt!
    Das Objekt entsteht erst zur Laufzeit; dein Code enthält nichts anderes als Blaupausen, Musterzeichnungen und Bauanträge.
    Quellcode lizensiert unter CC by SA 2.0 (Creative Commons Share-Alike)

    Meine Firma: Procyon Systems

    Selbstständiger Softwareentwickler & IT-Techniker.

    Neu

    Das ist mir in abgewandelter Form mehr oder weniger bekannt, wobei dieser Unterschied zwischen Interface und abstrakter Klasse denke ich durchaus nicht ganz so leicht aufzulösen ist wie das gedankliche Konzept eines Gebäudes und das angetragene Konzept eines Gebäudes.
    Es ging mir bei den anderen Fragen eher um die syntaktischen Feinheiten in der Deklaration und Implementation von Interfaces. Die dann auch noch alle bei den access modifiern zusammen liefen und gerade hierzu die Dokumentation auf mich verwirrend schien.

    Neu

    Haudruferzappeltnoch schrieb:

    Es ging mir bei den anderen Fragen eher um die syntaktischen Feinheiten in der Deklaration und Implementation von Interfaces.

    Ja, das dachte ich mir. Aber solche Themen locken gerne auch mal komplette Neulinge an, weshalb es IMO durchaus sinnvoll ist, diese grundlegenden Informationen anzugeben.

    Jede OOP-Implementierung hat ihre Tücken und man kann auch nicht immer zwei Sprachen miteinander.

    Im Sinne der "klassischen" OOP, macht es schlicht keinen Sinn, Defaultimplementierungen oder gar andere Sichtbarkeitsstufen in Interfaces zu haben; wenn man schon soweit ist, dann kann man die Interfaces gleich sein lassen und auf rein abstrakte Klassen setzen - so macht es C++ z.B.
    Ist man puristisch unterwegs (ich würde mich zu solchen zählen), dann ignoriert man die neuen Funktionen und verwendet die Funktionen so, wie es damals vorgesehen war.
    Quellcode lizensiert unter CC by SA 2.0 (Creative Commons Share-Alike)

    Meine Firma: Procyon Systems

    Selbstständiger Softwareentwickler & IT-Techniker.

    Neu

    siycah schrieb:

    wenn man schon soweit ist, dann kann man die Interfaces gleich sein lassen und auf rein abstrakte Klassen setzen

    Mit der Aussage wäre ich Vorsichtig. Dotnet kann keine Mehrfachvererbung, wie sie z.B. bei C++ funktioniert. Das geht nur über Interfaces. Zusätzlich kann man so auch type constraints für generische Funktionen definieren:

    C#-Quellcode

    1. CFoo foo = new();
    2. CBar bar = new();
    3. CFooBar fooBar = new();
    4. Dummy.Execute(foo); // Error!
    5. Dummy.Execute(bar);
    6. Dummy.Execute(fooBar);
    7. internal interface IFoo
    8. {
    9. int Foo();
    10. }
    11. interface IBar
    12. {
    13. void Bar();
    14. }
    15. internal class CFoo : IFoo
    16. {
    17. public int Foo()
    18. {
    19. throw new NotImplementedException();
    20. }
    21. }
    22. class CBar : IBar
    23. {
    24. public void Bar()
    25. {
    26. throw new NotImplementedException();
    27. }
    28. }
    29. class CFooBar : IFoo, IBar
    30. {
    31. public void Bar()
    32. {
    33. throw new NotImplementedException();
    34. }
    35. public int Foo()
    36. {
    37. throw new NotImplementedException();
    38. }
    39. }
    40. static class Dummy
    41. {
    42. public static void Execute<T>(T v) where T : IBar
    43. {
    44. }
    45. }

    Neu

    ISliceUrPanties schrieb:

    Mit der Aussage wäre ich Vorsichtig. Dotnet kann keine Mehrfachvererbung, wie sie z.B. bei C++ funktioniert.

    Ja, da hast du natürlich Recht. In solchen Fällen kann man jedoch in der Regel ganz einfach die Interfaces zu einer abstrakten Klasse vereinen.
    Quellcode lizensiert unter CC by SA 2.0 (Creative Commons Share-Alike)

    Meine Firma: Procyon Systems

    Selbstständiger Softwareentwickler & IT-Techniker.