To extend on dtb's answer, I wrote the following transform class:
public class Transform<T, K>
{
Func<K, T> _getFunc1;
Func<K, K, T> _getFunc2;
Func<K, K, K, T> _getFunc3;
Action<K, T> _setFunc1;
Action<K, K, T> _setFunc2;
Action<K, K, K, T> _setFunc3;
public T this[K k1]
{
get
{
if (_getFunc1 == null) throw new ArgumentException();
return _getFunc1(k1);
}
set
{
if (_getFunc1 == null) throw new ArgumentException();
_setFunc1(k1, value);
}
}
public T this[K k1, K k2]
{
get
{
if (_getFunc2 == null) throw new ArgumentException();
return _getFunc2(k1, k2);
}
set
{
if (_getFunc2 == null) throw new ArgumentException();
_setFunc2(k1, k2, value);
}
}
public T this[K k1, K k2, K k3]
{
get
{
if (_getFunc3 == null) throw new ArgumentException();
return _getFunc3(k1, k2, k3);
}
set
{
if (_getFunc3 == null) throw new ArgumentException();
_setFunc3(k1, k2, k3, value);
}
}
public Transform(Func<K, T> getFunc) { this._getFunc1 = getFunc; }
public Transform(Func<K, T> getFunc, Action<K, T> setFunc)
: this(getFunc)
{
this._setFunc1 = setFunc;
}
public Transform(Func<K, K, T> getFunc) { this._getFunc2 = getFunc; }
public Transform(Func<K, K, T> getFunc, Action<K, K, T> setFunc)
: this(getFunc)
{
this._setFunc2 = setFunc;
}
public Transform(Func<K, K, K, T> getFunc) { this._getFunc3 = getFunc; }
public Transform(Func<K, K, K, T> getFunc, Action<K, K, K, T> setFunc)
: this(getFunc)
{
this._setFunc3 = setFunc;
}
}
Allowing you to create sample classes like the following:
class TransformUser
{
int[, ,] _array = new int[4, 4, 4];
public Transform<int, int> Normal;
public Transform<int, int> Transformed;
public TransformUser()
{
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
for (int k = 0; k < 4; k++)
_array[i, j, k] = i * j * k;
Normal = new Transform<int, int>((x, y, z) => _array[x, y, z]);
Transformed = new Transform<int, int>((x, y, z) => _array[x, y / 2, z]);
}
}
With a use like the following:
TransformUser tu = new TransformUser();
Console.WriteLine(tu.Normal[2, 3, 2]);
Console.WriteLine(tu. Transformed[2, 3, 2]);