C#玩转指针(二):预处理器、using、partial关键字与region的妙用
欲練神功,引刀自宮。為了避免內(nèi)存管理的煩惱,Java咔嚓一下,把指針砍掉了。當年.Net也追隨潮流,咔嚓了一下,化名小桂子,登堂入室進了皇宮。康熙往下面一抓:咦?還在?——原來是假太監(jiān)韋小寶。
打開unsafe選項,C#指針就biu的一下子蹦出來了。指針很強大,沒必要拋棄這一強大的工具。誠然,在大多數(shù)情況下用不上指針,但在特定的情況下還是需要用到的。比如:
(1)大規(guī)模的運算中使用指針來提高性能;
(2)與非托管代碼進行交互;
(3)在實時程序中使用指針,自行管理內(nèi)存和對象的生命周期,以減少GC的負擔。
目前使用指針的主要語言是C和C++。但是由于語法限制,C和C++中的指針的玩法很單調(diào),在C#中,可以進行更優(yōu)雅更好玩的玩法。本文是《重新認識C#: 玩轉(zhuǎn)指針》一文的續(xù)篇,主要是對《重新認識C#: 玩轉(zhuǎn)指針》內(nèi)容進行總結(jié)和改進。
?
C#下使用指針有兩大限制:
(1)使用指針只能操作struct,不能操作class;
(2)不能在泛型類型代碼中使用未定義類型的指針。
第一個限制沒辦法突破,因此需要將指針操作的類型設(shè)為struct。struct + 指針,恩,就把C#當更好的C來用吧。對于第二個限制,寫一個預(yù)處理器來解決問題。
?
下面是我寫的簡單的C#預(yù)處理器的代碼,不到200行:
代碼 ??1?using?System;???2?using?System.Collections.Generic;?
??3?using?System.IO;?
??4?using?System.Text;?
??5?using?System.Text.RegularExpressions;?
??6?
??7?namespace?Orc.Util.Csmacro?
??8?{?
??9?????class?Program?
?10?????{?
?11?????????static?Regex?includeReg?=?new?Regex("#region\\s+include.+\\s+#endregion");?
?12?????????static?Regex?mixinReg?=?new?Regex("(?<=#region\\s+mixin\\s)[\\s|\\S]+(?=#endregion)");?
?13?????????///?<summary>?
?14?????????///?Csmacro?[dir|filePath]?
?15?????????///?
?16?????????///?語法:?
?17?????????///?????#region?include?""?
?18?????????///?????#endregion?
?19?????????///?????
?20?????????///?</summary>?
?21?????????///?<param?name="args"></param>?
?22?????????static?void?
?23?????????????#region?include<>?
?24?????????????????Main?
?25?????????????#endregion?
?26?????????????(string[]?args)?
?27?????????{?
?28?????????????if?(args.Length?!=?1)?
?29?????????????{?
?30?????????????????PrintHelp();?
?31?????????????????return;?
?32?????????????}?
?33?
?34?????????????String?filePath?=?args[0];?
?35?
?36?????????????Path.GetDirectoryName(filePath);?
?37?????????????String?dirName?=?Path.GetDirectoryName(filePath);?
?38?#if?DEBUG?
?39?????????????Console.WriteLine("dir:"?+?dirName);?
?40?#endif?
?41?????????????String?fileName?=?Path.GetFileName(filePath);?
?42?#if?DEBUG?
?43?????????????Console.WriteLine("file:"?+?fileName);?
?44?#endif?
?45?
?46?????????????if?(String.IsNullOrEmpty(fileName))?
?47?????????????{?
?48?????????????????Csmacro(new?DirectoryInfo(dirName));?
?49?????????????}?
?50?????????????else?
?51?????????????{?
?52?????????????????if?(fileName.EndsWith(".cs")?==?false)?
?53?????????????????{?
?54?????????????????????Console.WriteLine("Csmacro只能處理后綴為.cs的源程序.");?
?55?????????????????}?
?56?????????????????else?
?57?????????????????{?
?58?????????????????????Csmacro(new?FileInfo(fileName));?
?59?????????????????}?
?60?????????????}?
?61?
?62?????????????Console.WriteLine("[Csmacro]:處理完畢.");?
?63?
?64?#if?DEBUG?
?65?????????????Console.ReadKey();?
?66?#endif?
?67?????????}?
?68?
?69?????????static?void?Csmacro(DirectoryInfo?di)?
?70?????????{?
?71?????????????Console.WriteLine("[Csmacro]:進入目錄"?+?di.FullName);?
?72?
?73?????????????foreach?(FileInfo?fi?in?di.GetFiles("*.cs",?SearchOption.AllDirectories))?
?74?????????????{?
?75?????????????????Csmacro(fi);?
?76?????????????}?
?77?????????}?
?78?
?79?????????static?void?Csmacro(FileInfo?fi)?
?80?????????{?
?81?????????????String?fullName?=?fi.FullName;?
?82?????????????if?(fi.Exists?==?false)?
?83?????????????{?
?84?????????????????Console.WriteLine("[Csmacro]:文件不存在-"?+?fullName);?
?85?????????????}?
?86?????????????else?if?(fullName.EndsWith("_Csmacro.cs"))?
?87?????????????{?
?88?????????????????return;?
?89?????????????}?
?90?????????????else?
?91?????????????{?
?92?????????????????String?text?=?File.ReadAllText(fullName);?
?93?
?94?????????????????DirectoryInfo?parrentDirInfo?=?fi.Directory;?
?95?
?96?????????????????MatchCollection?mc?=?includeReg.Matches(text);?
?97?????????????????if?(mc?==?null?||?mc.Count?==?0)?return;?
?98?????????????????else?
?99?????????????????{?
100?????????????????????Console.WriteLine("[Csmacro]:處理文件"?+?fullName);?
101?
102?????????????????????StringBuilder?sb?=?new?StringBuilder();?
103?
104?????????????????????Int32?from?=?0;?
105?????????????????????foreach?(Match?item?in?mc)?
106?????????????????????{?
107?????????????????????????sb.Append(text.Substring(from,?item.Index?-?from));?
108?????????????????????????from?=?item.Index?+?item.Length;?
109?????????????????????????sb.Append(Csmacro(parrentDirInfo,?item.Value));?
110?????????????????????}?
111?
112?????????????????????sb.Append(text.Substring(from,?text.Length?-?from));?
113?
114?????????????????????String?newName?=?fullName.Substring(0,?fullName.Length?-?3)?+?"_Csmacro.cs";?
115?????????????????????if?(File.Exists(newName))?
116?????????????????????{?
117?????????????????????????Console.WriteLine("[Csmacro]:刪除舊文件"?+?newName);?
118?????????????????????}?
119?????????????????????File.WriteAllText(newName,?sb.ToString());?
120?????????????????????Console.WriteLine("[Csmacro]:生成文件"?+?newName);?
121?????????????????}?
122?????????????}?
123?????????}?
124?
125?????????static?String?Csmacro(DirectoryInfo?currentDirInfo,?String?text)?
126?????????{?
127?????????????String?outfilePath?=?text.Replace("#region",?String.Empty).Replace("#endregion",?String.Empty).Replace("include",String.Empty).Replace("\"",String.Empty).Trim();?
128?????????????try?
129?????????????{?
130?????????????????if?(Path.IsPathRooted(outfilePath)?==?false)?
131?????????????????{?
132?????????????????????outfilePath?=?currentDirInfo.FullName?+?@"\"?+?outfilePath;?
133?????????????????}?
134?????????????????FileInfo?fi?=?new?FileInfo(outfilePath);?
135?????????????????if?(fi.Exists?==?false)?
136?????????????????{?
137?????????????????????Console.WriteLine("[Csmacro]:文件"?+?fi.FullName?+?"不存在.");?
138?????????????????????return?text;?
139?????????????????}?
140?????????????????else?
141?????????????????{?
142?????????????????????return?GetMixinCode(File.ReadAllText(fi.FullName));?
143?????????????????}?
144?????????????}?
145?????????????catch?(Exception?ex)?
146?????????????{?
147?????????????????Console.WriteLine("[Csmacro]:出現(xiàn)錯誤("?+?outfilePath?+?")-"?+?ex.Message);?
148?????????????}?
149?????????????finally?
150?????????????{?
151?????????????}?
152?????????????return?text;?
153?????????}?
154?
155?????????static?String?GetMixinCode(String?txt)?
156?????????{?
157?????????????Match?m?=?mixinReg.Match(txt);?
158?????????????if?(m.Success?==?true)?
159?????????????{?
160?????????????????return?m.Value;?
161?????????????}?
162?????????????else?return?String.Empty;?
163?????????}?
164?
165?????????static?void?PrintHelp()?
166?????????{?
167?????????????Console.WriteLine("Csmacro?[dir|filePath]");?
168?????????}?
169?????}?
170?}
然后編譯為 Csmacro.exe ,放入系統(tǒng)路徑下。在需要使用預(yù)處理器的項目中添加 Pre-build event command lind:
Csmacro.exe $(ProjectDir)
Visual Studio 有個很好用的關(guān)鍵字 “region” ,我們就把它當作我們預(yù)處理器的關(guān)鍵字。include 一個文件的語法是:
#region include "xxx.cs"
#endregion
一個文件中可以有多個 #region include 塊。
被引用的文件不能全部引用,因為一個C#文件中一般包含有 using,namespace … 等,全部引用的話會報編譯錯誤。因此,在被引用文件中,需要通過關(guān)鍵字來規(guī)定被引用的內(nèi)容:
#region mixin
…
#endregion
這個預(yù)處理器比較簡單。被引用的文件中只能存在一個 #region mixin 塊,且在這個region的內(nèi)部,不能有其它的region塊。
預(yù)處理器 Csmacro.exe 的作用就是找到所有 cs 文件中的 #region include 塊,根據(jù) #region include? 路徑找到被引用文件,將該文件中的 #region mixin 塊 取出,替換進 #region include 塊中,生成一個以_Csmacro.cs結(jié)尾的新文件 。
由于C#的兩個語法糖“partial” 和 “using”,預(yù)處理器非常好用。如果沒有這兩個語法糖,預(yù)處理器會很丑陋不堪。(誰說語法糖沒價值!一些小小的語法糖,足以實現(xiàn)新的編程范式。)
partial 關(guān)鍵字 可以保證一個類型的代碼存在幾個不同的源文件中,這保證了預(yù)處理器的執(zhí)行,您可以像寫正常的代碼一樣編寫公共部分代碼,并且正常編譯。
using 關(guān)鍵字可以為類型指定一個的別名。這是一個不起眼的語法糖,卻在本文中非常重要:它可以為不同的類型指定一個相同的類型別名。之所以引入預(yù)處理器,就是為了復(fù)用包含指針的代碼。我們可以將代碼抽象成兩部分:變化部分和不變部分。一般來說,變化部分是類型的型別,如果還有其它非類型的變化,我們也可以將這些變化封裝成新的類型。這樣一來,我們可以將變化的類型放在源文件的頂端,使用using 關(guān)鍵字,命名為固定的別名。然后把不變部分的代碼,放在 #region mixin 塊中。這樣的話,讓我們需要 #region include 時,只需要在 #region include? 塊的前面(需要在namespace {} 的外部)為類型別名指定新的類型。
舉例說明,位圖根據(jù)像素的格式可以分為很多種,這里假設(shè)有兩種圖像,一種是像素是一個Byte的灰度圖像ImageU8,一個是像素是一個Argb32的彩色圖像ImageArgb32。ImageU8代碼如下:
代碼 ?1?public?class?ImageU8?2?{
?3?????public?Int32?Width?{?get;?set;?}
?4?????public?Int32?Height?{?get;?set;?}
?5?
?6?????public?unsafe?Byte*?Pointer;
?7?????public?unsafe?void?SetValue(Int32?row,?Int32?col,?Byte?value)
?8?????{
?9?????????Pointer[row?*?Width?+?col]?=?value;
10?????}
11?}
?在 ImageArgb32 中,我們也要寫重復(fù)的代碼:
?
代碼 ?1?public?class?ImageArgb32?2?{
?3?????public?Int32?Width?{?get;?set;?}
?4?????public?Int32?Height?{?get;?set;?}
?5?
?6?????public?unsafe?Argb32*?Pointer;
?7?????public?unsafe?void?SetValue(Int32?row,?Int32?col,?Argb32?value)
?8?????{
?9?????????Pointer[row?*?Width?+?col]?=?value;
10?????}
11?}
?
對于 Width和Height屬性,我們可以建立基類來進行抽象和復(fù)用,然而,對于m_pointer和SetValue方法,如果放在基類中,則需要抹去類型信息,且變的十分丑陋。由于C#不支持泛型類型的指針,也無法提取為泛型代碼。
使用 Csmacro.exe 預(yù)處理器,我們就可以很好的處理。
首先,建立一個模板文件 Image_Template.cs?
代碼 ?1?using?TPixel?=?System.Byte;??2?
?3?using?System;?
?4?
?5?namespace?XXX.Hidden?
?6?{?
?7?????class?Image_Template?
?8?????{?
?9?????????public?Int32?Width?{?get;?set;?}?
10?????????public?Int32?Height?{?get;?set;?}?
11?
12?????????#region?mixin?
13?
14?????????public?unsafe?TPixel*?Pointer;?
15?????????public?unsafe?void?SetValue(Int32?row,?Int32?col,?TPixel?value)?
16?????????{?
17?????????????Pointer[row?*?Width?+?col]?=?value;?
18?????????}?
19?
20?????????#endregion?
21?????}?
22?}
然后建立一個基類 BaseImage,再從BaseImage派生ImageU8和ImageArgb32。兩個派生類都是 partial 類:
代碼 ?1?using?System;??2?using?System.Collections.Generic;?
?3?using?System.Text;?
?4?
?5?namespace?XXX?
?6?{?
?7?????public?class?BaseImage?
?8?????{?
?9?????????public?Int32?Width?{?get;?set;?}?
10?????????public?Int32?Height?{?get;?set;?}?
11?????}?
12?
13?????public?partial?class?ImageU8?:?BaseImage?
14?????{?
15?????}?
16?
17?????public?partial?class?ImageArgb32?:?BaseImage?
18?????{?
19?????}?
20?}
下面我們建立一個 ImageU8_ClassHelper.cs 文件,來 #region include 引用上面的模板文件:
?1?using?TPixel?=?System.Byte;??2?
?3?using?System;?
?4?namespace?XXX?
?5?{?
?6?????public?partial?class?ImageU8?
?7?????{?
?8?????????#region?include?"Image_Template.cs"?
?9?????????#endregion?
10?????}?
11?}
編譯,編譯器會自動生成文件 “ImageU8_ClassHelper_Csmacro.cs” 。將這個文件引入項目中,編譯通過。這個文件內(nèi)容是:
代碼 ?1?using?TPixel?=?System.Byte;??2?
?3?using?System;?
?4?namespace?XXX?
?5?{?
?6?????public?partial?class?ImageU8?
?7?????{
?8?
?9?????????public?unsafe?TPixel*?Pointer;?
10?????????public?unsafe?void?SetValue(Int32?row,?Int32?col,?TPixel?value)?
11?????????{?
12?????????????Pointer[row?*?Width?+?col]?=?value;?
13?????????}?
14?
15?????}?
16?}
對于 ImageArgb32 類也可以進行類似操作。
?
從這個例子可以看出,使用 partial 關(guān)鍵字,能夠讓原代碼、模板代碼、ClassHelper代碼三者共存。使用 using 關(guān)鍵字,可以分離出代碼中變化的部分出來。
?
下面是我寫的圖像操作的一些模板代碼:
(1)通過模板提供指針和索引器:
代碼 ?1?using?TPixel?=?System.Byte;??2?using?TCache?=?System.Int32;?
?3?using?TKernel?=?System.Int32;?
?4?
?5?using?System;?
?6?using?System.Collections.Generic;?
?7?using?System.Text;?
?8?
?9?namespace?Orc.SmartImage.Hidden?
10?{?
11?????public?abstract?class?Image_Template?:?UnmanagedImage<TPixel>?
12?????{?
13?????????private?Image_Template()?
14?????????????:?base(1,1)?
15?????????{?
16?????????????throw?new?NotImplementedException();?
17?????????}?
18?
19?????????#region?mixin?
20?
21?????????public?unsafe?TPixel*?Start?{?get?{?return?(TPixel*)this.StartIntPtr;?}?}?
22?
23?????????public?unsafe?TPixel?this[int?index]?
24?????????{?
25?????????????get?
26?????????????{?
27?????????????????return?Start[index];?
28?????????????}?
29?????????????set?
30?????????????{?
31?????????????????Start[index]?=?value;?
32?????????????}?
33?????????}?
34?
35?????????public?unsafe?TPixel?this[int?row,?int?col]?
36?????????{?
37?????????????get?
38?????????????{?
39?????????????????return?Start[row?*?this.Width?+?col];?
40?????????????}?
41?????????????set?
42?????????????{?
43?????????????????Start[row?*?this.Width?+?col]?=?value;?
44?????????????}?
45?????????}?
46?
47?????????public?unsafe?TPixel*?Row(Int32?row)?
48?????????{?
49?????????????if?(row?<?0?||?row?>=?this.Height)?throw?new?ArgumentOutOfRangeException("row");?
50?????????????return?Start?+?row?*?this.Width;?
51?????????}?
52?
53?????????#endregion?
54?????}?
55?}
?
(2)通過模板提供常用的操作和Lambda表達式支持
代碼 ??1?using?TPixel?=?System.Byte;???2?using?TCache?=?System.Int32;?
??3?using?TKernel?=?System.Int32;?
??4?
??5?using?System;?
??6?using?System.Collections.Generic;?
??7?using?System.Text;?
??8?
??9?namespace?Orc.SmartImage.Hidden?
?10?{?
?11?????static?class?ImageClassHelper_Template?
?12?????{?
?13?????????#region?mixin?
?14?
?15?????????public?unsafe?delegate?void?ActionOnPixel(TPixel*?p);?
?16?????????public?unsafe?delegate?void?ActionWithPosition(Int32?row,?Int32?column,?TPixel*?p);?
?17?????????public?unsafe?delegate?Boolean?PredicateOnPixel(TPixel*?p);?
?18?
?19?????????public?unsafe?static?void?ForEach(this?UnmanagedImage<TPixel>?src,?ActionOnPixel?handler)?
?20?????????{?
?21?????????????TPixel*?start?=?(TPixel*)src.StartIntPtr;?
?22?????????????TPixel*?end?=?start?+?src.Length;?
?23?????????????while?(start?!=?end)?
?24?????????????{?
?25?????????????????handler(start);?
?26?????????????????++start;?
?27?????????????}?
?28?????????}?
?29?
?30?????????public?unsafe?static?void?ForEach(this?UnmanagedImage<TPixel>?src,?ActionWithPosition?handler)?
?31?????????{?
?32?????????????Int32?width?=?src.Width;?
?33?????????????Int32?height?=?src.Height;?
?34?
?35?????????????TPixel*?p?=?(TPixel*)src.StartIntPtr;?
?36?????????????for?(Int32?r?=?0;?r?<?height;?r++)?
?37?????????????{?
?38?????????????????for?(Int32?w?=?0;?w?<?width;?w++)?
?39?????????????????{?
?40?????????????????????handler(w,?r,?p);?
?41?????????????????????p++;?
?42?????????????????}?
?43?????????????}?
?44?????????}?
?45?
?46?????????public?unsafe?static?void?ForEach(this?UnmanagedImage<TPixel>?src,?TPixel*?start,?uint?length,?ActionOnPixel?handler)?
?47?????????{?
?48?????????????TPixel*?end?=?start?+?src.Length;?
?49?????????????while?(start?!=?end)?
?50?????????????{?
?51?????????????????handler(start);?
?52?????????????????++start;?
?53?????????????}?
?54?????????}?
?55?
?56?????????public?unsafe?static?Int32?Count(this?UnmanagedImage<TPixel>?src,?PredicateOnPixel?handler)?
?57?????????{?
?58?????????????TPixel*?start?=?(TPixel*)src.StartIntPtr;?
?59?????????????TPixel*?end?=?start?+?src.Length;?
?60?????????????Int32?count?=?0;?
?61?????????????while?(start?!=?end)?
?62?????????????{?
?63?????????????????if?(handler(start)?==?true)?count++;?
?64?????????????????++start;?
?65?????????????}?
?66?????????????return?count;?
?67?????????}?
?68?
?69?????????public?unsafe?static?Int32?Count(this?UnmanagedImage<TPixel>?src,?Predicate<TPixel>?handler)?
?70?????????{?
?71?????????????TPixel*?start?=?(TPixel*)src.StartIntPtr;?
?72?????????????TPixel*?end?=?start?+?src.Length;?
?73?????????????Int32?count?=?0;?
?74?????????????while?(start?!=?end)?
?75?????????????{?
?76?????????????????if?(handler(*start)?==?true)?count++;?
?77?????????????????++start;?
?78?????????????}?
?79?????????????return?count;?
?80?????????}?
?81?
?82?????????public?unsafe?static?List<TPixel>?Where(this?UnmanagedImage<TPixel>?src,?PredicateOnPixel?handler)?
?83?????????{?
?84?????????????List<TPixel>?list?=?new?List<TPixel>();?
?85?
?86?????????????TPixel*?start?=?(TPixel*)src.StartIntPtr;?
?87?????????????TPixel*?end?=?start?+?src.Length;?
?88?????????????while?(start?!=?end)?
?89?????????????{?
?90?????????????????if?(handler(start)?==?true)?list.Add(*start);?
?91?????????????????++start;?
?92?????????????}?
?93?
?94?????????????return?list;?
?95?????????}?
?96?
?97?????????public?unsafe?static?List<TPixel>?Where(this?UnmanagedImage<TPixel>?src,?Predicate<TPixel>?handler)?
?98?????????{?
?99?????????????List<TPixel>?list?=?new?List<TPixel>();?
100?
101?????????????TPixel*?start?=?(TPixel*)src.StartIntPtr;?
102?????????????TPixel*?end?=?start?+?src.Length;?
103?????????????while?(start?!=?end)?
104?????????????{?
105?????????????????if?(handler(*start)?==?true)?list.Add(*start);?
106?????????????????++start;?
107?????????????}?
108?
109?????????????return?list;?
110?????????}?
111?
112?????????///?<summary>?
113?????????///?查找模板。模板中值代表實際像素值。負數(shù)代表任何像素。返回查找得到的像素的左上端點的位置。?
114?????????///?</summary>?
115?????????///?<param?name="template"></param>?
116?????????///?<returns></returns>?
117?????????public?static?unsafe?List<System.Drawing.Point>?FindTemplate(this?UnmanagedImage<TPixel>?src,?int[,]?template)?
118?????????{?
119?????????????List<System.Drawing.Point>?finds?=?new?List<System.Drawing.Point>();?
120?????????????int?tHeight?=?template.GetUpperBound(0)?+?1;?
121?????????????int?tWidth?=?template.GetUpperBound(1)?+?1;?
122?????????????int?toWidth?=?src.Width?-?tWidth?+?1;?
123?????????????int?toHeight?=?src.Height?-?tHeight?+?1;?
124?????????????int?stride?=?src.Width;?
125?????????????TPixel*?start?=?(TPixel*)src.SizeOfType;?
126?????????????for?(int?r?=?0;?r?<?toHeight;?r++)?
127?????????????{?
128?????????????????for?(int?c?=?0;?c?<?toWidth;?c++)?
129?????????????????{?
130?????????????????????TPixel*?srcStart?=?start?+?r?*?stride?+?c;?
131?????????????????????for?(int?rr?=?0;?rr?<?tHeight;?rr++)?
132?????????????????????{?
133?????????????????????????for?(int?cc?=?0;?cc?<?tWidth;?cc++)?
134?????????????????????????{?
135?????????????????????????????int?pattern?=?template[rr,?cc];?
136?????????????????????????????if?(pattern?>=?0?&&?srcStart[rr?*?stride?+?cc]?!=?pattern)?
137?????????????????????????????{?
138?????????????????????????????????goto?Next;?
139?????????????????????????????}?
140?????????????????????????}?
141?????????????????????}?
142?
143?????????????????????finds.Add(new?System.Drawing.Point(c,?r));?
144?
145?????????????????Next:?
146?????????????????????continue;?
147?????????????????}?
148?????????????}?
149?
150?????????????return?finds;?
151?????????}?
152?
153?????????#endregion?
154?????}?
155?}
配合lambda表達式,用起來很爽。在方法“FindTemplate”中,有這一句:
if (pattern >= 0 && srcStart[rr * stride + cc] != pattern)
其中 srcStart[rr * stride + cc] 是 TPixel 不定類型,而 pattern 是 int 類型,兩者之間需要進行比較,但是并不是所有的類型都提供和整數(shù)之間的 != 操作符。為此,我建立了個新的模板 TPixel_Template。
?
(3)通過模板提供 != 操作符 的定義
代碼 ?1?using?TPixel?=?System.Byte;??2?using?System;?
?3?
?4?namespace?Orc.SmartImage.Hidden?
?5?{?
?6?????public?struct?TPixel_Template?
?7?????{?
?8?????????/*?
?9?????????#region?mixin?
10?
11?????????public?static?Boolean?operator?==(TPixel?lhs,?int?rhs)?
12?????????{?
13?????????????throw?new?NotImplementedException();?
14?????????}?
15?
16?????????public?static?Boolean?operator?!=(TPixel?lhs,?int?rhs)?
17?????????{?
18?????????????throw?new?NotImplementedException();?
19?????????}?
20?
21?????????public?static?Boolean?operator?==(TPixel?lhs,?double?rhs)?
22?????????{?
23?????????????throw?new?NotImplementedException();?
24?????????}?
25?
26?????????public?static?Boolean?operator?!=(TPixel?lhs,?double?rhs)?
27?????????{?
28?????????????throw?new?NotImplementedException();?
29?????????}?
30?
31?????????public?static?Boolean?operator?==(TPixel?lhs,?float?rhs)?
32?????????{?
33?????????????throw?new?NotImplementedException();?
34?????????}?
35?
36?????????public?static?Boolean?operator?!=(TPixel?lhs,?float?rhs)?
37?????????{?
38?????????????throw?new?NotImplementedException();?
39?????????}?
40?
41?????????#endregion?
42?
43?????????*/?
44?????}?
45?}
這里,在 #region mixin? 塊被注釋掉了,不注釋掉編譯器會報錯。注釋之后,不會影響程序預(yù)處理。
?
通過 ClassHelper類來使用模板:
代碼 ?1?using?System;??2?using?System.Collections.Generic;?
?3?using?System.Text;?
?4?
?5?namespace?Orc.SmartImage?
?6?{?
?7?????using?TPixel?=?Argb32;?
?8?????using?TCache?=?System.Int32;?
?9?????using?TKernel?=?System.Int32;?
10?
11?????public?static?partial?class?ImageArgb32ClassHelper?
12?????{?
13?????????#region?include?"ImageClassHelper_Template.cs"?
14?????????#endregion?
15?????}?
16?
17?????public?partial?class?ImageArgb32?
18?????{?
19?????????#region?include?"Image_Template.cs"?
20?????????#endregion?
21?????}?
22?
23?????public?partial?struct?Argb32?
24?????{?
25?????????#region?include?"TPixel_Template.cs"?
26?????????#endregion?
27?????}?
28?}?
?
由于 Argb32 未提供和 int 之間的比較,因此,在這里 #region include "TPixel_Template.cs"。而Byte可以與int比較,因此,在ImageU8中,就不需要#region include "TPixel_Template.cs":?
代碼 ?3?using?System;??4?using?System.Collections.Generic;?
?5?using?System.Text;?
?6?
?7?namespace?Orc.SmartImage?
?8?{?
?9?????using?TPixel?=?System.Byte;?
10?????using?TCache?=?System.Int32;?
11?????using?TKernel?=?System.Int32;?
12?
13?????public?static?partial?class?ImageU8ClassHelper?
14?????{?
15?????????#region?include?"ImageClassHelper_Template.cs"?
16?????????#endregion?
17?????}?
18?
19?????public?partial?class?ImageU8?
20?????{?
21?????????#region?include?"Image_Template.cs"?
22?????????#endregion?
23?????}?
24?}
?
是不是很有意思呢?強大的指針,結(jié)合C#強大的語法和快速編譯,至少在圖像處理這一塊是很好用的。
?
總結(jié)
以上是生活随笔為你收集整理的C#玩转指针(二):预处理器、using、partial关键字与region的妙用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 读《编程之道》-对于程序员的抽象描述
- 下一篇: Array.Copy 方法 总结