C#中是否存在类似代码同义词的内容?

时间:2013-03-17 17:14:51

标签: c#

例如我有一些代码:

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

其中xx不是myArray[i, j, k]的值,而是该代码的同义词,=>是此构造的某种声明语法。

我希望使用此功能来确保使用myArray[i, j, k]乘法使用完全相同的代码,而不会在某些地方获得myArray[j, i, k]

可能C#可以做那样的事情,没有丑陋的语法?我的意思是安全代码,而不是不安全的内存指针。或者我的观点可能有问题吗?


我为可能不正确的想法定义道歉。我想使用这个技巧(“代码同义词”或类似的东西)作为语言的常规特征(?或编译器等),不仅仅是在这种情况下。特殊类或函数在特定情况下是好的,但一般来说它们会导致代码量的显着增加,我想避免这种情况。

5 个答案:

答案 0 :(得分: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 ..方法通常不会抛出异常。

答案 1 :(得分: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));

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

答案 2 :(得分: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()));

答案 3 :(得分:0)

最后一句话要求明显的回应。看起来你想使用像代码生成器这样的东西。

像C预处理器这样的东西似乎符合要求:

#define xx myArray[i, j, k]

嗯,这确实不是......通常的“观点”,但好消息是,您可以在C#项目中简单地使用CPP预处理器。

思路:

  • 将其设为预建步骤。
  • 从.cs.cpp文件生成.cs

答案 4 :(得分: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]));
}

当然,做这样的事情才真正有意义,如果你不止一次这样做的话。否则答案是否定的,你不能以更好或更安全的方式做到这一点。你可以使用一些疯狂的反射方法,但我认为这不合适。只需确保这样的代码部分经过单元测试,您就不应该最终遇到索引问题。