82

const-correctnessのポイントは、ユーザーが変更または削除できないインスタンスのビューを提供できるようにすることです。コンパイラーは、const関数内からconstnessを解除するとき、またはconstオブジェクトの非const関数を使用しようとするときに指摘することにより、これをサポートします。では、constアプローチをコピーせずに、同じ目的を持つC#で使用できる方法論はありますか?

私は不変性を認識していますが、それは実際には名前を付けるコンテナオブジェクトには引き継がれませんが、1つの例です。

4

7 に答える 7

63

私もこの問題に何度も遭遇し、最終的にインターフェイスを使用しました。

C# は任意の形式であり、C++ の進化形でさえあるという考えを捨てることが重要だと思います。これらは、ほぼ同じ構文を共有する 2 つの異なる言語です。

私は通常、クラスの読み取り専用ビューを定義することにより、C# で「定数の正確性」を表現します。

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; }
    }
}
于 2008-09-22T13:19:36.140 に答える
28

const 狂気 (または関数型プログラミング用語での純粋性) の利点を得るには、c# の String クラスのように、クラスが不変になるようにクラスを設計する必要があります。

このアプローチは、オブジェクトを読み取り専用としてマークするよりもはるかに優れています。不変クラスを使用すると、マルチタスク環境でデータを簡単に渡すことができるからです。

于 2008-09-22T10:45:44.840 に答える
23

System.Collections.Generics コンテナーの多くには、不変のコレクションを返す AsReadOnly メソッドがあることに注意してください。

于 2008-09-23T13:40:33.990 に答える
4

C#にはそのような機能はありません。引数は、値または参照で渡すことができます。ref修飾子を指定しない限り、参照自体は不変です。ただし、参照されるデータは不変ではありません。したがって、副作用を避けたい場合は注意する必要があります。

MSDN:

パラメータの受け渡し

于 2008-09-22T10:30:01.367 に答える
2

不変オブジェクトを作成するために、コンストラクターで初期化する読み取り専用フィールドを使用する他のいくつかの方法に同意します。

    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; }
    }
  }

または、プロパティにアクセス スコープを追加することもできます。つまり、public get と 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; }
    }
  }
于 2008-09-25T11:26:05.373 に答える
2

インターフェイスはその答えであり、実際には C++ の "const" よりも強力です。const は、「const」が「メンバーを設定しない、またはメンバーを設定する何かを呼び出さない」と定義されている問題に対する万能のソリューションです。これは、多くのシナリオでの const-ness の省略形ですが、すべてではありません。たとえば、一部のメンバーに基づいて値を計算するだけでなく、結果もキャッシュする関数を考えてみましょう。C++ では、これは非 const と見なされますが、ユーザーの観点からは本質的に const です。

インターフェイスを使用すると、クラスから提供する機能の特定のサブセットをより柔軟に定義できます。const-ness が必要ですか? 変更メソッドのないインターフェイスを提供するだけです。いくつかの設定を許可し、他の設定を許可したくないですか? それらのメソッドだけを含むインターフェイスを提供します。

于 2008-09-22T17:33:42.237 に答える
1
  • constキーワードは、プリミティブ型や文字列などのコンパイル時定数に使用できます
  • readonlyキーワードは、参照型などの実行時定数に使用できます

読み取り専用の問題は、参照(ポインター)のみを一定にできることです。参照されている(指し示されている)ものは、引き続き変更できます。これはトリッキーな部分ですが、それを回避する方法はありません。定数オブジェクトを実装するということは、可変のメソッドやプロパティを公開しないようにすることを意味しますが、これは厄介です。

効果的なC#:C#を改善するための50の特定の方法(項目2-constよりも読み取り専用を優先)も参照してください。

于 2008-09-22T12:32:18.483 に答える