日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > C# >内容正文

C#

C#模板编程(1):有了泛型,为什么还需要模板?

發布時間:2023/12/20 C# 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C#模板编程(1):有了泛型,为什么还需要模板? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

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<T0>,這里T代表每一個像素的存儲類型。可以是Byte,Short,Int32,Int64,Single,Double等。然后,核是一個泛型類,Kernel<T1>,這里還有第三個泛型類,就是用于存放中間數據的Image<T2>。為什么需要T2呢?假如T0是Byte,T1是帶有Scale的Int32(如,Scale=9,每個元素值=1的3*3矩陣),計算的中間結果會超出Byte的最大值,需要一個不同類型緩存來存儲這個中間數據。

只用泛型的話,解決不了這個問題。第一點,Byte,Short,Int32,Int64,Single,Double之間未實現共同接口;第二點,為提升性能,Image<T>采用非托管內存實現,使用指針進行操作,而泛型中無法使用泛型指針。

使用C#模板可以解決這個問題——代碼照舊,只是在頭部寫下:Using T0=XXX;Using T1=XXX;Using T2=XXX;即可。

由于欠缺源代碼的Include機制,當要編寫新的濾波器時,需要把相同的代碼復制過去,然后更改頭部的Using ……。但無論如何,這樣使用,還是比在代碼中直接寫明類型,然后復制、粘帖、替換新類型的可讀性以及可維護性要好。

如果.Net允許源代碼的Include,C#的模板編程將變得更為流暢(比起C++還是欠缺很多)。不知道等后續.Net版本開放編譯服務之后,會不會有更優雅的寫法。

下面是我隨便寫下的一段對圖像進行空間線性濾波的代碼(不要看具體算法,具體算法是極端錯誤的,且不完整的,只用看看編碼風格就行了,寫這段代碼只為驗證這種編程模式的優點和缺點):

using System;?
using System.Collections.Generic;?
using System.Text;

using T = System.Byte;?
using CacheT = System.Int32;?
using K = System.Int32;

namespace Orc.SmartImage.UnmanagedImage?
{?
??? public static class FilterHelper?
??? {?
??????? public unsafe static UnmanagedImage<T> Filter(this UnmanagedImage<T> src, FilterKernel<K> filter)?
??????? {?
??????????? K* kernel = stackalloc K[filter.Length];

??????????? Int32 srcWidth = src.Width;?
??????????? Int32 srcHeight = src.Height;?
??????????? Int32 kWidth = filter.Width;?
??????????? Int32 kHeight = filter.Height;

??????????? T* start = (T*) src.StartIntPtr;?
??????????? T* lineStart = start;?
??????????? T* pStart = start;?
??????????? T* pTemStart = pStart;?
??????????? T* pT;?
??????????? Int32* pK;

??????????? for (int c = 0; c < srcWidth; c++)?
??????????? {?
??????????????? for (int r = 0; r < srcHeight; r++)?
??????????????? {?
??????????????????? pTemStart = pStart;?
??????????????????? pK = kernel;

??????????????????? Int32 val = 0;?
??????????????????? for (int kc = 0; kc < kWidth; kc++)?
??????????????????? {?
??????????????????????? pT = pStart;?
??????????????????????? for (int kr = 0; kr < kHeight; kr++)?
??????????????????????? {?
??????????????????????????? val += *pK * *pT;?
??????????????????????????? pT++;?
??????????????????????????? pK++;?
??????????????????????? }

??????????????????????? pStart += srcWidth;?
??????????????????? }

??????????????????? pStart = pTemStart;?
??????????????????? pStart++;?
??????????????? }

??????????????? lineStart += srcWidth;?
??????????????? pStart = lineStart;?
??????????? }?
??????????? return null;?
??????? }?
??? }?
}

?

是不是很像模板編程呢?

本文轉自xiaotie博客園博客,原文鏈接http://www.cnblogs.com/xiaotie/archive/2010/03/22/1691705.html如需轉載請自行聯系原作者


xiaotie?集異璧實驗室(GEBLAB)

總結

以上是生活随笔為你收集整理的C#模板编程(1):有了泛型,为什么还需要模板?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。