C#编程の模板
2021-05-14 14:27
标签:存储 short 场景 col com collect 存在 length clu C#泛型编程已经深入人心了。为什么又提出C#模板编程呢?因为C#泛型存在一些局限性,突破这些局限性,需要使用C#方式的模板编程。由于C#语法、编译器、IDE限制,C#模板编程没有C++模板编程使用方便,但是,仍然可以解决一些问题。 下面先看C#泛型编程的两个限制: (1)类型约束问题。 C#泛型的类型约束是个很严重的问题。 假设需要写一个泛型方法,这个方法有2个参数,然后方法返回结果是这两个参数的和。 这样的泛型方法无法直接实现。因为Byte,Int32等等并没有公共接口。 没有公共接口,但又想借助泛型来节省代码,减少维护量。怎么办呢? 我之前写过2篇博客《实现.net下的动态代理》、《实现.net下的动态代理(续)-多对象Mixin》,通过Ducking Typing来实现,但这种实现方式不自然,且性能低下,只适合对性能不敏感的场景。 (2)泛型指针问题。 泛型程序中无法使用泛型指针,因为编译器编译时无法知道具体类型的Size,这对写unsafe代码是很大的限制。 因此,我们需要C#模板编程。C#模板编程说起来很简单,它借助的是C#的一个语法——Using T0=T1。它没有C++那么自然,因为它缺乏C/C++源文件的Include机制。你可以将整块的文件在不同的类之间进行复制和粘帖。虽然复制和粘帖是一大邪恶,但总比复制/粘帖/替换要好很多。 下面是C#模板编程的一个重要应用——图像处理的空间线性滤波。关于空间线性滤波可参见各种图像处理的书,这里不做介绍。 我们假定图像是一个泛型类Image 只用泛型的话,解决不了这个问题。第一点,Byte,Short,Int32,Int64,Single,Double之间未实现共同接口;第二点,为提升性能,Image 使用C#模板可以解决这个问题——代码照旧,只是在头部写下:Using T0=XXX;Using T1=XXX;Using T2=XXX;即可。 由于欠缺源代码的Include机制,当要编写新的滤波器时,需要把相同的代码复制过去,然后更改头部的Using ……。但无论如何,这样使用,还是比在代码中直接写明类型,然后复制、粘帖、替换新类型的可读性以及可维护性要好。 如果.Net允许源代码的Include,C#的模板编程将变得更为流畅(比起C++还是欠缺很多)。不知道等后续.Net版本开放编译服务之后,会不会有更优雅的写法。 下面是我随便写下的一段对图像进行空间线性滤波的代码(不要看具体算法,具体算法是极端错误的,且不完整的,只用看看编码风格就行了,写这段代码只为验证这种编程模式的优点和缺点): using System; using T = System.Byte; namespace Orc.SmartImage.UnmanagedImage Int32 srcWidth = src.Width; T* start = (T*) src.StartIntPtr; for (int c = 0; c { Int32 val = 0; pStart += srcWidth; pStart = pTemStart; lineStart += srcWidth; C#编程の模板 标签:存储 short 场景 col com collect 存在 length clu 原文地址:http://www.cnblogs.com/xietianjiao/p/7521656.html
using System.Collections.Generic;
using System.Text;
using CacheT = System.Int32;
using K = System.Int32;
{
public static class FilterHelper
{
public unsafe static UnmanagedImage
{
K* kernel = stackalloc K[filter.Length];
Int32 srcHeight = src.Height;
Int32 kWidth = filter.Width;
Int32 kHeight = filter.Height;
T* lineStart = start;
T* pStart = start;
T* pTemStart = pStart;
T* pT;
Int32* pK;
for (int r = 0; r {
pTemStart = pStart;
pK = kernel;
for (int kc = 0; kc {
pT = pStart;
for (int kr = 0; kr {
val += *pK * *pT;
pT++;
pK++;
}
}
pStart++;
}
pStart = lineStart;
}
return null;
}
}
}