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

歡迎訪問 生活随笔!

生活随笔

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

C#

typedef struct 先声明后定义_C++模版和C#泛型求同存异录(二)typedef

發布時間:2025/3/20 C# 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 typedef struct 先声明后定义_C++模版和C#泛型求同存异录(二)typedef 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

(這篇文章有些復雜,請來回慢慢看)

typedef

C++語言中的typedef簡直是個神奇的關鍵字,它的最簡單的作用就是把一種類型重新命名,定義個別名。很像宏定義,但又不是。在編程中使用typedef目的一般有兩個,一個是給變量定義一個易記且意義明確的新名字,另一個是簡化一些比較復雜的類型聲明。但在C++模版編程之中,它還有個非常巧妙的用處:類型之間的傳遞和約束!

C++ typedef

來看個例子(真的用的好開心)

template <class T> class Matrix {class Accessor{public:typedef T DATATYPE;} }template <typename ACCESSOR> class Scanner {public:typedef typename ACCESSOR::DATATYPE DATATYPE; }

一個簡單的使用例子是這樣的

typedef float DATATYPE; Matrix<DATATYPE> data; //數據源 Matrix<DATATYPE>::Accessor accessor(data); //訪問器 Scanner<Matrix<DATATYPE>::Accessor> scanner(accessor) //檢索器

請問Scanner::DATATYPE是什么數據類型?答案就是float!

也就是說,上面的案例之中,兩個模版類的數據類型出現了傳遞,類型出現了相互依賴的關系。以上代碼如果不做特殊設計,那么就只能寫出這樣的代碼了

typedef float DATATYPE; Matrix<DATATYPE> data; Accessor<DATATYPE> accessor(data); Scanner<DATATYPE> scanner(accessor)

邏輯是明白的,但是相互的依賴關系是要靠約定的,而不是代碼本身能控制的。僅是typedef的巧妙使用,使得 T->Accessor::DATATYPE->Scanner::DATATYPE ,數據類型出現了傳遞行為。也就是說通過typedef,使的Scanner::DATATYPE,Matrix::Accessor::DATATYPE,DATATYPE,float都是相同的類型,只是別名不同而已。這些不同的別名擁有不同的語義,且存在相互依賴關系。

類型傳遞?

那么更加進一步問題來了,C#能做到這個嗎?

首先C#沒有typedef關鍵字,也沒有typename關鍵字,所以似乎我們只能寫出最直白的代碼(忽略using關鍵字定義別名的功能,這個功能太弱)

class Matrix<T> {class Accessor{Accessor(Matrix<T> matrix){}} } class Scanner<T> {Scanner(Matrix<T>.Accessor accessor){} }Matrix<float> data; Accessor<float> accessor(data); Scanner<float> scanner(accessor)

這樣的代碼顯然只能依賴于程序員不能犯錯,而從代碼本身角度來說,也是缺乏一些類型約束功能。

當然似乎這樣的代碼也不會出錯,因為C#是強類型的,如果我們這樣寫

Matrix<int> data; Accessor<float> accessor(data); //會報錯,會提示無法從Matrix<int>轉換成Matrix<float> Scanner<float> scanner(accessor)

但是我期望的代碼至少是

Matrix<float> test = new Matrix<float>(); Matrix<float>.Accessor accessor(data); Scanner<Matrix<float>.Accessor> scanner(accessor)

讓我們把C++的設計思路直接用在C#版本

嘗試過程跳過,我給出一個最接近的版本。用到關鍵字dynamic,where,不懂的同學請自己查下幫助文檔。

public class AccessorBase {public dynamic value; }public class Matrix<T> {public class Accessor : AccessorBase{public new T value;} }public class Scanner<Accessor> where Accessor : AccessorBase {public Scanner(Accessor accessor){value = accessor.value;}private dynamic value; public dynamic GetValue() { return value; } }

簡化過的測試代碼如下

Matrix<float>.Accessor accessor = new Matrix<float>.Accessor(); accessor.value = (float)99.0; Scanner<Matrix<float>.Accessor> scanner = new Scanner<Matrix<float>.Accessor>(accessor); dynamic tmp = scanner.GetValue(); //tmp的值為null,但是我希望是99.0

問題出在 value = accessor.value; 這一句代碼中 因為Accessor和AccessorBase的value只能保留一個。

不用where,那么accessor.value無法調用,除非使用反射?;蛘呤褂胐ynamic關鍵字

public Scanner(dynamic accessor) {value = accessor.value; //但accessor缺乏類型約束 }

反正我試了好久沒有啥解決辦法。回到C++的typedef功能 typedef

那么我們能在C#中模擬出來typedef嗎,結論是可以!

直接上代碼

public abstract class Typedef<T, TDerived> where TDerived : Typedef<T, TDerived>, new() {private T _value;public static implicit operator T(Typedef<T, TDerived> t){return t == null ? default : t._value;}public static implicit operator Typedef<T, TDerived>(T t){return t == null ? default : new TDerived { _value = t };} }

這是適合任何類型重定義的類。

class DATATYPE : Typedef<double, DATATYPE> { }; class SDATATYPE : Typedef<DATATYPE, SDATATYPE> { };

缺陷是DATATYPE和SDATATYPE是兩個完全不同的類,因為C#是強類型。使用起來有些別扭

DATATYPE data = (DATATYPE)99.0; SDATATYPE sdata = (SDATATYPE)(DATATYPE)99.0;

先忽略這一點,讓我們看看前面的泛型代碼該怎么改

默默測試兩天之后,我發現,就算模擬了一個typedef的操作,依然還是做不到類型傳遞。

因為C#沒法寫出類似下面的代碼

typedef typename ACCESSOR::DATATYPE DATATYPE;

typename ACCESSOR::DATATYPE是告訴C++編譯器,ACCESSOR::DATATYPE是類型,雖然這個類型現在不知道是什么類型,但是就是個類型。然后C#可做不到這樣的事情,所以只能是黑人問好臉了。

最后我又只能回到最初的代碼,依賴于C#的強類型,保證在相互之間傳遞數據的時候,不會出錯:

class Matrix<T> {class Accessor{Accessor(Matrix<T> matrix){}} } class Scanner<T> {Scanner(Matrix<T>.Accessor accessor){} }Matrix<float> data; Accessor<float> accessor(data); Scanner<float> scanner(accessor)

后記

文章寫完了,為了探索這個可能性,我大概花費了3-4個晚上的休息時間。雖然路是不通的,但也對C#泛型和C++的模板代碼的設計思路更進一步了解了差異性。雖然這不算是什么成績,但我還是把整個過程整理了一篇文章。

雖然Typedef 效果沒有我設想的那么完美,但依然是一個很有效的typedef用法,特別可以支持任何Primitive類型,sealed class的繼承操作,這一點還是值得一提的。

Github有個類似功能很小的C#庫,叫LikeType,https://github.com/kleinwareio/LikeType 如果誰有興趣可以仔細去看下,它也實現了類似的功能。

最后修改于2019-12-17日,首發于公眾號:技術宅指北

總結

以上是生活随笔為你收集整理的typedef struct 先声明后定义_C++模版和C#泛型求同存异录(二)typedef的全部內容,希望文章能夠幫你解決所遇到的問題。

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