C# 泛型特化

C# 泛型不是 C++ 的模板类,并不支持特化和偏特化,但是使用一些技巧可以在一定程度上达到相同的目的。

原文是 po 在 stackoverflow 上的一个回答:A: Generic indexer overload specialization

一、泛型方法的特化

使用一个非泛型 helper 类和一个内嵌的泛型类可以实现对泛型方法的特化。

 1     internal static class IndexerImpl //non-generic static helper class
 2     {
 3         private static T IndexerDefaultImpl<T>(int i) => default(T); //default implementation
 4
 5         private static T IndexerImpl2<T>(int i) => default(T); //another implementation for short/int/long
 6
 7         private static string IndexerForString(int i) => (i * i).ToString(); //specialization for T=string
 8         private static DateTime IndexerForDateTime(int i) => new DateTime(i * i * i); //specialization for T=DateTime
 9
10         static IndexerImpl() //install the specializations
11         {
12             Specializer<string>.Fun = IndexerForString;
13             Specializer<DateTime>.Fun = IndexerForDateTime;
14
15             Specializer<short>.Fun = IndexerImpl2<short>;
16             Specializer<int>.Fun = IndexerImpl2<int>;
17             Specializer<long>.Fun = IndexerImpl2<long>;
18         }
19
20         internal static class Specializer<T> //specialization dispatcher
21         {
22             internal static Func<int, T> Fun;
23             internal static T Call(int i)
24                 => null != Fun
25                     ? Fun(i)
26                     : IndexerDefaultImpl<T>(i);
27         }
28     }
29
30     public class YourClass<T>
31     {
32         public T this[int i] => IndexerImpl.Specializer<T>.Call(i);
33     }

如果需要传入实例对返回结果进行计算,可以增加一个参数:

 1     internal static class IndexerImpl //non-generic static helper class
 2     {
 3         private static T IndexerDefaultImpl<T>(int i, YourClass<T> yourClass) => default(T); //default implementation
 4
 5         private static T IndexerImpl2<T>(int i, YourClass<T> yourClass) => default(T); //another implementation for short/int/long
 6
 7         private static string IndexerForString<T>(int i, YourClass<T> yourClass) => (i * i).ToString(); //specialization for T=string
 8         private static DateTime IndexerForDateTime<T>(int i, YourClass<T> yourClass) => new DateTime(i * i * i); //specialization for T=DateTime
 9
10         static IndexerImpl() //install the specializations
11         {
12             Specializer<string>.Fun = IndexerForString;
13             Specializer<DateTime>.Fun = IndexerForDateTime;
14
15             Specializer<short>.Fun = IndexerImpl2;
16             Specializer<int>.Fun = IndexerImpl2;
17             Specializer<long>.Fun = IndexerImpl2;
18         }
19
20         internal static class Specializer<T> //specialization dispatcher
21         {
22             internal static Func<int, YourClass<T>, T> Fun;
23             internal static T Call(int i, YourClass<T> yourClass)
24                 => null != Fun
25                     ? Fun(i, yourClass)
26                     : IndexerDefaultImpl(i, yourClass);
27         }
28     }
29
30     public class YourClass<T>
31     {
32         public T this[int i] => IndexerImpl.Specializer<T>.Call(i, this);
33     }

二、泛型方法的偏特化

偏特化也是差不多的做法,只不过帮助类变成了以不需要特化的类型构成的泛型类:

 1     internal static class GetValueImpl<R, S>
 2     {
 3         private static T DefImpl<T>(R r, S s) => default(T);
 4         private static int IntRet(R r, S s) => int.MaxValue;
 5
 6         internal static class Specializer<T>
 7         {
 8             internal static Func<R, S, T> Fun;
 9             internal static T Call(R r, S s) => null != Fun ? Fun(r, s) : DefImpl<T>(r, s);
10         }
11
12         static GetValueImpl()
13         {
14             Specializer<int>.Fun = IntRet;
15         }
16     }
17
18     public class TestClass
19     {
20         public T GetValue<R, S, T>(R r, S s) => GetValueImpl<R, S>.Specializer<T>.Call(r, s);
21     }

以上代码片段中,被偏特化的是 GetValue 方法中的 T 类型参数,当 T=int 的时候,实际被调用的方法就是 GetValueImpl.IntRet 方法,其他情况是 GetValueImpl.DefImpl 方法。

三、泛型类的特化

泛型类的特化没有什么好的方法,只能采用继承特化类型泛型类的方式间接实现,并且将要特化处理的成员采用虚方法或者用 new 隐藏基类方法。

偏特化泛型类也可以采用差不多的方式实现。

具体做法可以参考 stackoverflow 上的这个答案:A: C# specialize generic class

时间: 2024-09-30 22:19:11

C# 泛型特化的相关文章

奇技淫巧:F#泛型特化的最终优化

上回讲到,F#中 module 里的泛型变量实际上是泛型函数.由此,在一个泛型特化的实现中出了岔子.最后通过泛型得以解决.使用 F# 来做泛型特化,相比 C# 有这个优势:F# 中直接支持函数赋值,而无须使用委托.避免了 C# 例子里面,为了节省 Lumbda 与委托之间的转换,而做出的丑陋的反射.拆箱操作.代码不再这么艰涩,我们重新来看看这段代码: module Mithra = type Cache<'T>() = static member val GetBytes: 'T->by

Java增强的泛型

尽管Java 8是2014年年初才发布的,而Java 9要等到2016年年中,但是目前有一些计划放到某个未来版本(希望是Java 10)中的特性已经合并了进来. 具体而言,有两个比较大的特性已经开始原型设计了,它们是增强的泛型(Enhanced Generics)和值类型(Value Types).有了增强的泛型,Java开发者可以编写像List<int>这样的代码,省去了对基本类型进行装箱的痛苦.新的泛型提案有些地方比较模糊(或者说微妙),需要细心处理,具体见Brian Goetz在最近的设

Swift开发黑科技:还在争论MVC和MVVM?现在你应该试试MVP!

本人原创,长文慎入,但此文绝对不会让你失望. WWDC2015已经过去一段时间了,我发现自从更新了Swift2.0到现在的Swift2.2,我只是跟着版本更新了所有需要更新的语法,依旧自以为是很熟练的Swift程序员.刚入职比较闲碰巧看到了1月份的中国首届Swift大会上大牛们的分享,突然陷入了思考,有了很多新想法又重温了几遍WWDC2015大会的视频,尤其是408和414号视频!!!我下定决心重构自己的代码,下面步入正题,结合Swift开发大会的一些分享,让我们谈谈架构. 通过一个简单的Dem

Uber使用Swift重写APP的踩坑经历及解决方案(转载)

我是托马斯·阿特曼,目前是Uber移动架构和框架组负责人.Uber现在的用户量已经达到数百万,这么大的用户量,Uber是如何用框架实现的呢? Swift与百位工程师的故事 - 原因.架构.经验 今天我想谈谈一百多名Uber工程师是如何使用Swift编程语言的,在上周三新发布的Rider App主应用程序全部都是用Swift语言重构的.接下来我的分享主要包括三个部分:选择Swift的原因.Uber新架构:重构经验. 优步的开端--重构的原因 这是整个移动团队四年前的样子(指向屏幕显示有三名工程师的

简单搜索--Paddle Mobile的技术实现和业务落地

Paddle Mobile是PaddlePaddle组织下的致力于嵌入式平台的深度学习框架,集成了百度移动端预测的实践经验,提供多平台支持,在工程实现支持及底层算法模型压缩的基础上,通过CPU.mall GPU等硬件加速,作用于DuerOS.百度APP.百度网盘APP等移动端场景.目前,Paddle Mobile在PaddlePaddle 0.14版本下已支持CPU.Mali GPU等平台,以及图像.人脸.OCR等模型.值得一提的是,它的体积极小,最小仅300K.今天这篇文章是由百度大搜索高级研

C#泛型-模板特化

class TClass<T, K> { } class SubTClass<T, C, K> : TClass<Char, K> { } class SubTClass1<K> : TClass<Char, K> { } class SubTClass2 : TClass<Char, int> { }

C++ 模板特化以及Typelist的相关理解

近日,在学习的过程中第一次接触到了Typelist的相关内容,比如Loki库有一本Modern C++ design的一本书,大概JD搜了一波没有译本,英文版600多R,瞬间从价值上看到了这本书的价值!!这是题外话.这本书十分经典.其内容对于一个C++新手来说需要时间来理解吸收.在这里记录一下自己的理解.日后发现错误会给予更正.如有有人碰巧看到了.欢迎指正. 参考了http://blog.csdn.net/gatieme/article/details/50953564 整篇内容分了三个部分:1

Java 泛型 Java使用泛型的意义

Java 泛型 Java使用泛型的意义 @author ixenos 直接意义 在编译时保证类型安全 根本意义 a) 类型安全问题源自可复用性代码的设计,泛型保证了类型安全的复用模板 b) 使用复用性模板时不用手动强制类型转换 三种泛型实现方式的优缺点 C++:模板方式实现,在编译时完全展开并且支持偏特化,类型精度高,代码共享差: Java 5:擦除方式实现,仅用于编译时类型检查,在运行时擦除,向后兼容性好,代码共享好,类型精度非常差: C# 2.0:混合方式实现,在运行时展开特化,类型精度高,

模板显式、隐式实例化和(偏)特化、具体化的详细分析(转)

这么多叫法,其实就是三种. 1. 显示实例化 2. 隐式实例化 3. 特化(=具体化).偏特化 一.实例化 1.显示.隐式实例化 什么是实例化:一个通过使用具体值替换模板参数,从模板产生的普通类,函数或者成员函数的过程. 显示实例化:通过名字可见,就是清楚的表明你要实例化的类型 隐式实例化:通过编译器自己推测判断要实例化的类型. 比如一个模板: template<class T> //函数模板实现  void swap(T &a, T &b) {     T temp;