0

chaps / chapettes、これに関連する質問があることは理解していますが、これは多少異なります-私が見つけることができたすべての関連する質問は、例として1つのパラメーターのみを使用しました. とにかく、要点:

今年は、Delphi で書かれたソース コードを C# に変換しました。これを超えて、私のタスクの範囲は、コード ベースを最適化し、全体的に改善することでした。ソース コードは、ソフトウェア エンジニアリングの原理や手法に関する知識や経験を持たない少数の個人によって書かれているため、一部のコードは不適切です。

とにかく、誰かが私の口論に提案/解決策を提供できるかもしれません:

現在、C# には 9 つの値を格納するためのクラスがあります。

class StoreStruct
{
    int A1 { get; set;}
    int B1 { get; set;}
    int C1 { get; set;}

    int A2 { get; set;}
    int B2 { get; set;}
    int C2 { get; set;}

    int A3 { get; set;}
    int B3 { get; set;}
    int C3 { get; set;}
}

今私が問題を抱えているのは、理想的には、このクラスのプロパティを参照によってメソッドに渡したいということです。しかし、私はこれができないことを知っています。代わりに、ソース コードは一時ローカル変数を作成することで機能し、これらを ref で渡し、クラス プロパティをこれらの値に割り当てます。これは次のように見ることができます。

private void MethodA()
{
    var temp = new StoreStruct();

    var a1 = 0;
    var b1 = 0;
    var c1 = 0;

    var a2 = 0;
    var b2 = 0;
    var c2 = 0;

    var a3 = 0;
    var b3 = 0;
    var c3 = 0;

    if (expression1)
    {
        MethodB(ref a1, ref b1, ref c1, 1, 1);

        temp.A1 = a1;
        temp.B1 = b1;
        temp.C1 = c1;       
    }

    if (expression2)
    {
        MethodB(ref a2, ref b2, ref c2, 2, 2);

        temp.A2 = a2;
        temp.B2 = b2;
        temp.C2 = c2;   
    }

    if (expression3)
    {
        MethodB(ref a3, ref b3, ref c3, 3, 3);

        temp.A3 = a3;
        temp.B3 = b3;
        temp.C3 = c3;   
    }
}

private void MethodB(ref int a, ref int b, ref int c, int num1, int num2)
{
    a = num1 + num2;
    b = num1 - num2;
    c = num1 * num2;
}

理想の世界でやりたいこと:

MethodB(ref temp.A1, ref temp.B1, ref temp.C1, 1, 1);

他の投稿を見て、これが C# で対応されていない理由を理解しており、率直に言って、その背後にある理由に同意します。他の投稿でいくつかの回避策といくつかの提案を見てきましたが、これらは 1 つのメソッド呼び出しと 1 つのパラメーターのみが ref によって渡される例にのみ関連しています。一時変数を渡さなくても MethodB のクラス プロパティを更新できるエレガントなソリューションはありますか?

4

8 に答える 8

1

からgettersとを削除するだけです。settersStoreStruct

于 2013-11-14T16:38:04.933 に答える
0

あなたのクラスには 3 つの値のセットがあるようです。このようなセットのクラスを作成すると、クラスに 3 つの値を持つことができます。

class ABC {
  int A { get; set; }
  int B { get; set; }
  int C { get; set; }
}

class StoreStruct {

  ABC ABC1 { get; set; }
  ABC ABC2 { get; set; }
  ABC ABC3 { get; set; }

  public StoreStruct {
    ABC1 = new ABC();
    ABC2 = new ABC();
    ABC3 = new ABC();
  }

}

ABCに値を渡すことができるようになりました。これは変更可能な値のセットであるため、パラメーターのキーワードはMethodB必要ありません。ref

private void MethodB(ABC abc, int num1, int num2) {
  abc.A = num1 + num2;
  abc.B = num1 - num2;
  abc.C = num1 * num2;
}

電話:

MethodB(temp.ABC1, 1, 1);

MethodBclass のメンバーを作成ABCして、値をメソッドに渡さないようにすることもできます。値に対してメソッドを呼び出します。

class ABC {
  int A { get; set; }
  int B { get; set; }
  int C { get; set; }

  public void MethodB(int num1, int num2) {
    A = num1 + num2;
    B = num1 - num2;
    C = num1 * num2;
  }
}

使用法:

temp.ABC1.MethodB(1, 1);
于 2013-11-14T16:37:17.030 に答える
0

クラスのすべてのプロパティを交換したいようです。OOP の世界では、これを行う最善の方法は、プロパティだけでなく、完全なクラスをメソッドに送信することです。

public void MethodB(ref StoreStruct store) {
 // store.A1=[...];
}
于 2013-11-14T16:40:05.720 に答える
0

そうですね、私だったらまず最初にここで本名をいくつか取得してみます。A1、B2 などとは何ですか? レジですか?子犬?宇宙そり?名前は、何が起こっているかを反映する必要があります。次に、理想的には、クラスは可能な限り独自のデータを変更する必要があるため、一連のフラグを渡すのではなく、オブジェクトを渡し、必要な変更を行うためにオブジェクトでできるだけ少ないメソッドを呼び出すという観点から考える傾向があります。 、特に後者が本当に鈍い名前を持っている場合。それが一般的な批判のように思われる場合は申し訳ありませんが、時間の経過とともにコードベースを改善する任務について言及したことになります. (それらが本当に構造体である場合、デバッグに役立つ可能性がある場合を除いて、プロパティはやり過ぎであることが常にわかりました)。

于 2013-11-14T16:36:21.967 に答える
0

うわー、この質問にはすでにたくさんの答えがあります。さて、ここに別のものがあります。次のような整数への参照として機能するクラスを作成してみてください。

class IntRef
{
   private int value;
   public IntRef(int value)
   {
      this.value = value;
   }

   public static implicit operator IntRef(int value)
   {
      return new IntRef(value);
   }

   public static implicit operator int(IntRef value)
   {
      return value.value;
   }
}

次に、int宣言とref intパラメーターを に変更しますIntRef

setただし、これを行うと、手順が実行されない可能性があることに注意してください。が変更された値に反応できるように、そのコードの一部をIntRefクラスに移動するか、イベントを発生させる必要がある場合があります。IntRefStoreStruct

于 2013-11-14T16:57:04.697 に答える
0

おそらく何か間違ったことをしており、参照を渡す必要のない方法で状態をカプセル化できるというジョナサンのコメントに同意します。

必要なことを行うために、ゲッター/セッターにバッキング変数を使用できます。

private int _a1;
public int A1
{
  get
  {
    return _a1;
  }
  set
  {
    _a1 = value;
  }
}

public void Foo()
{
  Bar(ref _a1);
}
于 2013-11-14T16:39:20.113 に答える
0

個人的には、質問で行った回避策を使用します。ただし、本当に必要な場合は、値を割り当てる関数にデリゲートを渡してから、関数内で呼び出す必要があります。

if (expression1)
{
    MethodB((a) => temp1.A1 = a, 
            (b) => temp1.B1 = b, 
            (c) => temp1.C1 = c, 
             1, 1);     
}

private void MethodB(Func<int> setA, 
                     Func<int> setB, 
                     Func<int> setC, 
                     int num1, int num2)
{
    setA(num1 + num2);
    setB(num1 - num2);
    setC(num1 * num2);
}
于 2013-11-14T16:35:01.107 に答える
0

プロパティは、getter および setter 関数呼び出しのシンタックス シュガーにすぎません。そのため、プロパティを参照渡しすることはできません。一般に、C# でrefパラメーターを使用している場合は、おそらく間違っています。

StoreStructオブジェクトを渡すだけで、関数にプロパティを設定させます。Aclassは参照型であるため、C# では基本的にすべてのオブジェクトが既定で "参照によって" 渡されます。

あなたの変更StoreStructはこれに役立ち、一連の狂気を排除すると思います:

class Thing {
    int A { get; set; }
    int B { get; set; }
    int C { get; set; }
}

class StoreStruct {  //  Not actually a struct!
    public readonly Thing thing1;
    public readonly Thing thing2;
    public readonly Thing thing3;
}

使用する:

private void MethodA()
{
    var temp = new StoreStruct();

    if (expression1)
    {
        MethodB(temp.thing1, 1, 1);     
    }

    if (expression2)
    {
        MethodB(temp.thing2, 1, 1);     
    }

    if (expression3)
    {
        MethodB(temp.thing3, 1, 1);     
    }
}

private void MethodB(Thing thing, int num1, int num2)
{
    thing.A = num1 + num2;
    thing.B = num1 - num2;
    thing.C = num1 * num2;
}
于 2013-11-14T16:35:26.050 に答える