Frage "Const Korrektheit" in C #


Der Punkt der const-Korrektheit ist es, eine Sicht auf eine Instanz bereitstellen zu können, die vom Benutzer nicht geändert oder gelöscht werden kann. Der Compiler unterstützt dies, indem er darauf hinweist, wenn Sie die Konstante aus einer Konst-Funktion herausbrechen oder versuchen, eine nicht-konstante Funktion eines Konstanten-Objekts zu verwenden. Also, ohne den const-Ansatz zu kopieren, gibt es eine Methode, die ich in C # verwenden kann, die die gleichen Enden hat?

Ich bin mir der Unveränderlichkeit bewusst, aber das überträgt sich nicht wirklich auf Containerobjekte, um nur ein Beispiel zu nennen.


75
2017-09-22 10:25


Ursprung


Antworten:


Ich bin auch oft auf dieses Problem gestoßen und habe schließlich Schnittstellen verwendet.

Ich denke, es ist wichtig, die Idee fallen zu lassen, dass C # irgendeine Form oder sogar eine Evolution von C ++ ist. Sie sind zwei verschiedene Sprachen, die fast die gleiche Syntax haben.

Normalerweise gebe ich in c # "const correctness" aus, indem ich eine schreibgeschützte Ansicht einer Klasse definiere:

public interface IReadOnlyCustomer
{
    String Name { get; }
    int Age { get; }
}

public class Customer : IReadOnlyCustomer
{
    private string m_name;
    private int m_age;

    public string Name
    {
        get { return m_name; }
        set { m_name = value; }
    }

    public int Age
    {
        get { return m_age; }
        set { m_age = value; }
    }
}

59
2017-09-22 13:19



Um die Vorteile von Const-Craziness (oder Reinheit in funktionalen Programmierbegriffen) zu nutzen, müssen Sie Ihre Klassen so gestalten, dass sie unveränderlich sind, genau wie die String-Klasse von c #.

Dieser Ansatz ist viel besser, als ein Objekt nur als schreibgeschützt zu markieren, da Sie mit unveränderlichen Klassen Daten problemlos in Multitasking-Umgebungen übertragen können.


28
2017-09-22 10:45



Ich wollte nur für Sie feststellen, dass viele Container von System.Collections.Generics eine AsReadOnly-Methode haben, die Ihnen eine unveränderbare Sammlung zurückgibt.


23
2017-09-23 13:40



C # verfügt nicht über diese Funktion. Sie können Argument nach Wert oder Verweis übergeben. Die Referenz selbst ist unveränderlich, wenn Sie nicht angeben ref Modifikator. Aber referenzierte Daten sind nicht unveränderbar. Sie müssen also vorsichtig sein, wenn Sie Nebenwirkungen vermeiden wollen.

MSDN:

Parameter übergeben


4
2017-09-22 10:30



Schnittstellen sind die Antwort und sind in C ++ tatsächlich mächtiger als "const". const ist eine Einheitslösung für das Problem, bei der "const" definiert ist als "setzt keine Mitglieder oder ruft etwas auf, das Mitglieder setzt". Das ist eine gute Kurzform für Const-Ness in vielen Szenarien, aber nicht für alle. Betrachten Sie zum Beispiel eine Funktion, die basierend auf einigen Elementen einen Wert berechnet, aber auch die Ergebnisse zwischenspeichert. In C ++ wird das als nicht konstant angesehen, obwohl es aus Benutzersicht im Wesentlichen konstant ist.

Schnittstellen geben Ihnen mehr Flexibilität beim Definieren der spezifischen Teilmenge von Funktionen, die Sie in Ihrer Klasse bereitstellen möchten. Willst du Konstanz? Stellen Sie einfach eine Schnittstelle ohne Mutationsmethoden zur Verfügung. Willst du einige Dinge einstellen, aber nicht andere? Stellen Sie eine Schnittstelle nur für diese Methoden bereit.


3
2017-09-22 17:33



Stimmen Sie mit einigen anderen überein, indem Sie schreibgeschützte Felder verwenden, die Sie im Konstruktor initialisieren, um unveränderliche Objekte zu erstellen.

    public class Customer
    {
    private readonly string m_name;
    private readonly int m_age;

    public Customer(string name, int age)
    {
        m_name = name;
        m_age = age;
    }

    public string Name
    {
        get { return m_name; }
    }

    public int Age
    {
        get { return m_age; }
    }
  }

Alternativ können Sie auch den Zugriffsbereich für die Eigenschaften hinzufügen, z. B. public get und protected set?

    public class Customer
    {
    private string m_name;
    private int m_age;

    protected Customer() 
    {}

    public Customer(string name, int age)
    {
        m_name = name;
        m_age = age;
    }

    public string Name
    {
        get { return m_name; }
        protected set { m_name = value; }
    }

    public int Age
    {
        get { return m_age; }
        protected set { m_age = value; }
    }
  }

3
2017-09-25 11:26



  • Das const Schlüsselwort kann für Kompilierzeitkonstanten wie primitive Typen und Zeichenfolgen verwendet werden
  • Das schreibgeschützt Schlüsselwort kann für Laufzeitkonstanten wie Referenztypen verwendet werden

Das Problem mit schreibgeschütztist, dass es nur erlaubt, dass die Referenz (Zeiger) konstant ist. Das Ding, auf das verwiesen wird (auf das verwiesen wird), kann noch modifiziert werden. Dies ist der schwierige Teil, aber es gibt keinen Weg um ihn herum. Konstante Objekte zu implementieren bedeutet, dass sie keine veränderbaren Methoden oder Eigenschaften offenlegen, aber das ist peinlich.

Siehe auch Effektive C #: 50 spezifische Möglichkeiten zur Verbesserung Ihrer C # (Punkt 2 - Lese lieber nur const.)


2
2017-09-22 12:32