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 locals 允许您这样做

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

请注意,您不仅获得同义词,而且获得引用,这意味着数组索引仅被评估一次。

于 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 回答