c#中有类似代码同义词的东西吗?

本文关键字:同义词 代码 | 更新日期: 2023-09-27 18:04:15

例如我有一些代码:

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#可以做这样的事情,没有丑陋的语法?我指的是安全代码,而不是不安全的内存指针。或者是我的观点有问题?
我很抱歉我对我的想法的定义可能是错误的。我想使用这个技巧("代码同义词"或类似的东西)作为语言的常规特征(?或编译器等),不仅在这种情况下。专门化的类或函数在特定情况下是好的,但通常它们会导致代码量的显著增加,我希望避免这种情况。

c#中有类似代码同义词的东西吗?

可以使用一些函数吗?例如:

在你的代码中:

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..方法通常不会抛出异常。

您可以实现自己的矩阵类型来存储实际的索引

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

注意,您得到的不仅是同义词,还有引用,这意味着数组索引只求值一次。

您可以使用匿名委托。

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

最后一句话需要明显的回应。看来你想使用代码生成器之类的东西。

类似C预处理器的东西似乎符合要求:

#define xx myArray[i, j, k]

嗯,那确实不是……通常的"观点",但好消息是,您可以简单地在c#项目中使用CPP预处理器。

的想法:

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

你可以自己写一个这样的函数:

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

当然,做这样的事情只有在你做了不止一次的时候才有意义。否则,答案是否定的,因为你不能以更好或更安全的方式做到这一点。你可以使用一些疯狂的反射方法,但我认为在这里不合适。只要确保这样的代码段经过单元测试,就不会出现索引问题。