4

たとえば、私はいくつかのコードを持っています:

if (myArray[i, j, k] == someValue)
  myArray[i, j, k] = someOtherValue;
else
  throw new Exception(string.Format("value {0} is wrong!", myArray[i, j, k]));

と、ちょっと危険そうです。次のような「コード同義語」が欲しいです。

var xx => myArray[i, j, k];
if (xx == someValue)
  xx = someOtherValue;
else
  throw new Exception(string.Format("value {0} is wrong!", xx));

wherexxは の値ではなく、myArray[i, j, k]そのコードの同義語であり、=>この構成体のある種の宣言構文です。

myArray[i, j, k]この機能を使用して、乗算の使用がまったく同じコードになるようにしたいと思いmyArray[j, i, k]ます。どこかに入るリスクはありません。

C# は醜い構文なしで、そのようなことを行うことができるでしょうか? 安全でないメモリポインタではなく、安全なコードを意味します。それとも、私の視点に何か問題がありますか?


私の考えの定義が間違っている可能性があることをお詫び申し上げます。このトリック(「コード同義語」など)を、この単一のケースだけでなく、言語(?またはコンパイラなど)の通常の機能として使用したいと思います。特殊なクラスや関数は特定のケースでは良いのですが、一般的にコード量の大幅な増加につながるため、これは避けたいと考えています。

4

5 に答える 5

4

これには何らかの機能を使用できますか?例えば:

あなたのコードで:

UpdateElement(ref myArray[i, j, k], someValue, someOtherValue);

そして機能:

void UpdateElement(ref int element, int compareWith, int value)
{
     if (element == compareWith)
         element = value;
     else
         throw new Exception(string.Format("Value {0} is wrong!", element));
}

UPD: メソッドの名前を 'TryUpdateElement' から 'UpdateElement' に変更しました。Try.. メソッドは通常、例外をスローしません。

于 2013-03-17T18:07:51.830 に答える
1

実際のインデックスを格納する独自のマトリックス型を実装できます

public class Matrix<T>
{
    private T[, ,] _array;

    public Matrix(int sizeX, int sizeY, int sizeZ)
    {
        _array = new T[sizeX, sizeY, sizeZ];
    }

    public T this[int i, int j, int k]
    {
        get { return _array[i, j, k]; }
        set { _array[i, j, k] = value; }
    }

    public int CurrentI { get; set; }
    public int CurrentJ { get; set; }
    public int CurrentK { get; set; }

    public void SetCurrentCell(int i, int j, int k)
    {
        CurrentI = i;
        CurrentJ = j;
        CurrentK = k;
    }

    public T Current
    {
        get { return _array[CurrentI, CurrentJ, CurrentK]; }
        set { _array[CurrentI, CurrentJ, CurrentK] = value; }
    }

    public static implicit operator T(Matrix<T> matrix)
    {
        return matrix.Current;
    }

    // The assignment operator (=) cannot be overloaded. But we can overload |
    // instead, allowing us to write: m |= value in order to perform an assignment.
    public static Matrix<T> operator |(Matrix<T> m, T value)
    {
        m.Current = value;
        return m;
    }
}

次のように使用できます。

var m = new Matrix<int>(3, 3, 3);
m[0, 2, 1] = 77;
m.SetCurrentCell(0, 2, 1);
m.Current = 88;
int value = m; // Using the implicit operator and the current indexes
m |= 20; // Using |= as assignment operator

ジェネリック アプローチには、数値演算の実装がより困難になるという欠点があります (+、-、​​、/ などの数学演算はジェネリック型では定義されません)。ただし、数値計算を実装する派生クラスでジェネリック型を解決できます

public class DoubleMatrix : Matrix<double> {
    public static DoubleMatrix operator +(DoubleMatrix a, DoubleMatrix b)
    {
        //TODO: Implement + operator
        return m;
    }

    //TODO: Implement other operators
}

C# 7.0 では ref ローカルが導入され、まさにそれが可能になりました

ref int xx = ref myArray[i, j, k];
if (xx == someValue)
    xx = someOtherValue;
else
    throw new Exception(string.Format("value {0} is wrong!", xx));

シノニムだけでなく参照も取得することに注意してください。つまり、配列インデックスは 1 回だけ評価されます。

于 2013-03-17T17:36:58.073 に答える
0

これには匿名デリゲートを使用できます。

var get_xx = delegate(){ return myArray[i, j, k];};
var set_xx = delegate(int v){ myArray[i, j, k] = v;};

if (get_xx() == someValue)
  set_xx(someOtherValue);
else
  throw new Exception(string.Format("value {0} is wrong!", get_xx()));
于 2013-03-17T17:17:58.283 に答える
0

その最後の文は、明白な応答を求めています。コードジェネレーターのようなものを使いたいようです。

C プリプロセッサのようなものは、法案に適合するように見えます。

#define xx myArray[i, j, k]

まあ、それは確かに... 通常の「視点」ではありませんが、良いニュースは、C# プロジェクトで CPP プリプロセッサを簡単に使用できることです。

アイデア:

  • ビルド前のステップにします。
  • .cs.cpp ファイルから .cs を生成する
于 2013-03-17T17:19:48.267 に答える
0

次のようなことを可能にする関数を自分で書くことができます:

UpdateMatrixValueIf(myArray, i, j, k, (v) => v == someValue, someOtherValue);

そして、次のように実装します。

public void UpdateMatrixValueIf<T>(T[,,] array, int i, int j, int k, Func<T, bool> check, T newValue)
{
    if (check(array[i, j, k]))
        array[i, j, k] = newValue;
    else
        throw new Exception(string.Format("Value {0} is wrong!", array[i, j, k]));
}

もちろん、このようなことをするのは、複数回行う場合にのみ意味があります。そうでなければ、答えは単純にノーであり、より良い、またはより安全な方法でそれを行うことはできません. クレイジーなリフレクション メソッドを使用することもできますが、ここでは適切ではないと思います。そのようなコード セクションが単体テストされていることを確認してください。そうすれば、インデックスの問題が発生することはありません。

于 2013-03-17T17:50:00.477 に答える