例如我有一些代码:
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#可以做那样的事情,没有丑陋的语法?我的意思是安全代码,而不是不安全的内存指针。或者我的观点可能有问题吗?
我为可能不正确的想法定义道歉。我想使用这个技巧(“代码同义词”或类似的东西)作为语言的常规特征(?或编译器等),不仅仅是在这种情况下。特殊类或函数在特定情况下是好的,但一般来说它们会导致代码量的显着增加,我想避免这种情况。
答案 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预处理器。
思路:
答案 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]));
}
当然,做这样的事情才真正有意义,如果你不止一次这样做的话。否则答案是否定的,你不能以更好或更安全的方式做到这一点。你可以使用一些疯狂的反射方法,但我认为这不合适。只需确保这样的代码部分经过单元测试,您就不应该最终遇到索引问题。