你可以使用一个包含嵌套泛型类的
helper class
,该类包含
Func/Action
委托,以实现索引器/属性/方法的特化。
internal static class IndexerImpl
{
private static T IndexerDefaultImpl<T>(int i) => default(T);
private static T IndexerImpl2<T>(int i) => default(T);
private static string IndexerForString(int i) => (i * i).ToString();
private static DateTime IndexerForDateTime(int i) => new DateTime(i * i * i);
static IndexerImpl()
{
Specializer<string>.Fun = IndexerForString;
Specializer<DateTime>.Fun = IndexerForDateTime;
Specializer<short>.Fun = IndexerImpl2<short>;
Specializer<int>.Fun = IndexerImpl2<int>;
Specializer<long>.Fun = IndexerImpl2<long>;
}
internal static class Specializer<T>
{
internal static Func<int, T> Fun;
internal static T Call(int i)
=> null != Fun
? Fun(i)
: IndexerDefaultImpl<T>(i);
}
}
public class YourClass<T>
{
public T this[int i] => IndexerImpl.Specializer<T>.Call(i);
}
如果你需要
YourClass
的实例来计算返回值,你可以添加一个参数来传递必需的信息:
internal static class IndexerImpl
{
private static T IndexerDefaultImpl<T>(int i, YourClass<T> yourClass) => default(T);
private static T IndexerImpl2<T>(int i, YourClass<T> yourClass) => default(T);
private static string IndexerForString<T>(int i, YourClass<T> yourClass) => (i * i).ToString();
private static DateTime IndexerForDateTime<T>(int i, YourClass<T> yourClass) => new DateTime(i * i * i);
static IndexerImpl()
{
Specializer<string>.Fun = IndexerForString;
Specializer<DateTime>.Fun = IndexerForDateTime;
Specializer<short>.Fun = IndexerImpl2;
Specializer<int>.Fun = IndexerImpl2;
Specializer<long>.Fun = IndexerImpl2;
}
internal static class Specializer<T>
{
internal static Func<int, YourClass<T>, T> Fun;
internal static T Call(int i, YourClass<T> yourClass)
=> null != Fun
? Fun(i, yourClass)
: IndexerDefaultImpl(i, yourClass);
}
}
public class YourClass<T>
{
public T this[int i] => IndexerImpl.Specializer<T>.Call(i, this);
}
当专门化一个通用的Indexer时,需要一个非通用的帮助类。
当专门化一个非通用类的通用属性/方法时,可以直接将默认实现/专门化和嵌套的专门化分派类放在您的类中。
需要注意的是,不要将专门化的安装放入通用类的静态构造函数中。
此外,如果您需要部分特化,可以使用一个通用的辅助类,其中参数化类型不需要进行特化:
internal static class GetValueImpl<R, S>
{
private static T DefImpl<T>(R r, S s) => default(T);
private static int IntRet(R r, S s) => int.MaxValue;
internal static class Specializer<T>
{
internal static Func<R, S, T> Fun;
internal static T Call(R r, S s) => null != Fun ? Fun(r, s) : DefImpl<T>(r, s);
}
static GetValueImpl()
{
Specializer<int>.Fun = IntRet;
}
}
public class TestClass
{
public T GetValue<R, S, T>(R r, S s) => GetValueImpl<R, S>.Specializer<T>.Call(r, s);
}
使用这种方式实现部分特化时,您需要注意,如果您使用不同的非特化类型多次调用嵌套的特化类,则助手类的静态构造函数将运行多次:
public void Test()
{
var foo = new TestClass();
var v1 = foo.GetValue<long, long, int>(1, 2);
var v2 = foo.GetValue<long, long, string>(1, 2);
var v3 = foo.GetValue<long, long, long>(1, 2);
var v4 = foo.GetValue<long, int, int>(1, 2);
var v5 = foo.GetValue<long, int, double>(1, 2);
}
请注意,对于
GetValueImpl<long, long>
和
GetValueImpl<long, int>
,静态构造函数将运行2次,因此不要在帮助类的静态构造函数中放置额外的代码。
c[i]=a[i]+b[i]
而检查30次if-else语句将比使用数组更耗时。我之所以问这个问题是因为C++端已经被优化,gpgpu部分也已经准备好并且被优化,只剩下这个C#访问部分需要优化。我正在优化瓶颈部分。例如:某人用2秒钟初始化数组,但gpgpu只需要0.5秒钟。但是使用C++数组和指针,两者都只需要0.5秒钟。 - huseyin tugrul buyukisikmyObject[42]
时,您期望调用哪个索引器重载? - O. R. MapperGet<T>(int index) {} Set<T>(int index, T value);
。是的,不太方便,但如果您正在进行性能优化-那可能是一个选项。 - Evk