1

クラスの外部から表示する必要があるフィールドを持つ C# クラスがありますが、クラス内からのみ変更する必要があります。ただし、問題は、フィールドが直接 (またはプロパティによって) ではなく、public mutator メソッドを介して更新されることです。

public class FirstClass
{
    public SecondClass TheField {get; private set;}

    public FirstClass()
    {
        TheField = new SecondClass();
    }

    public void SomeMethod()
    {
        // ...
        TheField.Update(/*parameters*/);
        // ...
    }
}

public class SecondClass
{
    // some fields  

    public SecondClass() { }

    public void Update(/*parameters*/)
    {       
        // do something
    }
}

つまり、メソッド Update() に FirstClass 内からのみアクセスできるようにしたいと考えています。

いくつかの可能な解決策と、私がそれらに満足できない理由:

  1. メソッドではなくセッターで SecondClass を変更します。- パラメータと多くの作業が必要なため、機能しません。
  2. Update() を public ではなく internal にします。- アセンブリ内から引き続きアクセスできますが、十分ではありません。
  3. FirstClass から SecondClass を変更します。メソッド Update() を FirstClass に移動し、非公開にして、必要なすべてのフィールドを SecondClass から公開します。・オブジェクト指向感が半端ない。
  4. SecondClass コンストラクターから Update() を呼び出し、更新が必要になるたびに SecondClass の新しいインスタンスを作成します。- SecondClass には変更されないものがいくつかあり、Update() を呼び出すたびに処理したいため、パフォーマンスが低下します。

これを行う方法はありますか?

4

5 に答える 5

4

@aquaragaの回答の基本的な実装ですが、代わりにインターフェースを使用しています:

public interface ISecond
{
    // some properties  
}

public class FirstClass
{
    private readonly SecondClass _TheField;
    public ISecond TheField { get { return _TheField; } }

    public FirstClass()
    {
        _TheField = new SecondClass();
    }

    public void SomeMethod()
    {
        // ...
        _TheField.Update(/*parameters*/);
        // ...
    }

    private class SecondClass : ISecond
    {
        // some properties  

        public void Update(/*parameters*/)
        {       
            // do something
        }
    }
}

基本的に、すべてのアクセス可能なメンバーを持ち、メソッドを持たないパブリック インターフェイスを公開しますUpdateUpdateメソッドを持つが、それ以外の場合は呼び出し元のコードにアクセスできないプライベート ネスト クラスを採用し、それをクラスとしてではなくインターフェイスとして公開します。

使用例:

FirstClass myFirst = ...
myFirst.SomeMethod(); //updates ok!
Console.WriteLine(myFirst.TheField.PropertyA); //can access properties of ISecond
myFirst.TheField.Update(); //compiler error!

1 つのポイントは、「一部のフィールド」の使用について言及していることです。インターフェースとして、フィールドではなくプロパティを持つことができます。それが契約違反になるかどうかはわかりません。

SecondClass編集:コードの重複を再利用して最小限に抑えるという意図について言及しました。簡単な修正の 1 つは、いくつかのabstractクラス、protected Updateメソッドを宣言し、internalコンストラクターを使用して (他のアセンブリがコンストラクターから継承できないようにするため)、Update最小限の実装で呼び出しを公開することです。

public abstract class SecondClassBase : ISecond
{
    // some properties

    internal SecondClassBase()
    {

    }

    protected void Update(/*parameters*/)
    {
        // do something
    }
}

次にFirstClass、ネストされたクラス以外は何も変更されません。

public class FirstClass
{
    private readonly SecondClass _TheField;
    public ISecond TheField { get { return _TheField; } }

    public FirstClass()
    {
        _TheField = new SecondClass();
    }

    public void SomeMethod()
    {
        // ...
        _TheField.Update(/*parameters*/);
        // ...
    }

    private class SecondClass : SecondClassBase
    {
        public new void Update(/*parameters*/)
        {       
            base.Update(/*parameters*/);
        }
    }
}

まだコードの重複がありますが、コードをコピーして貼り付けるだけです。Updateの実装ごとにプロパティやロジックを再宣言する必要はありませんFirstClass。メソッドの隠蔽を避けるために、メソッドの名前を別の名前に変更することもできnew Updateますが、以前と同じ呼び出しシグネチャを保持することにしました。

于 2013-06-07T12:51:17.610 に答える
1

UpdateableSecondClass1つの方法は、FirstClassにインナークラスと呼ばれるサブクラスを作成すること です。から継承しSecondClass、単一のメソッドを持ちます。Update()

メソッドはまったく必要ありませSecondClassん。Update()あなたはそれを世界の残りの部分に公開し続けることができます:

public SecondClass TheField {get; private set;}
于 2013-06-07T12:43:24.910 に答える
0

クリス・シンクレアの答えは素晴らしいです、これは単なる別のオプションです

public sealed class FirstClass : SecondClass
{
    public FirstClass()
    {

    }

    public void SomeMethod(int j)
    {
        base.Update(j);
    }
}

public abstract class SecondClass
{

    public SecondClass() { }

    protected void Update(int i)
    {
        Console.WriteLine(i.ToString());
    }
}

これは、FirstClass を介してメソッドにアクセスするためのものです。

于 2013-06-07T17:15:49.243 に答える