2013-09-28 73 views
1

假設我有一個基本的類層次結構是這樣的:轉換的通用結構,以相同的通用結構與不同類型的參數

public abstract class BaseClass { } 
public class X : BaseClass { } 
public class Y: BaseClass { } 

而且我有一個通用的結構,因爲這:

public struct MyStruct<T> 
    where T: BaseClass, new() 
{ 
} 

我然後可以創建一個實例如下:

var x = new MyStruct<X>(); 

現在我想提供一個操作(構造函數或轉換n運算符)上MyStruct,這讓我轉換MyStruct<X>MyStruct<Y>

MyStruct<Y> my = new MyStruct<X>(); 

當我寫一個構造函數如下:

public struct MyStruct<T> 
    where T: BaseClass, new() 
{ 
    public MyStruct(MyStruct<T2> value) 
     where T2: BaseClass, new() 
    { 
     ... 
    } 
} 

編譯器不明白我試圖做(它似乎無法區分MyStruct<T>MyStruct<T2>)。

如何將MyStruct<X>MyStruct<T>轉換爲MyStruct<Y>

回答

3

你不能在構造函數中做到這一點,但你應該能夠編寫一個轉換方法的結構,是這樣的:

public struct MyStruct<T> 
    where T: BaseClass, new() 
{ 
    // Convert this instance of MyStruct<T> to a new MyStruct<TOut> 
    public MyStruct<TOut> ToMyStruct<TOut>() 
    { 
     ... 
    } 
} 

這樣可以讓你寫:

struct2 = struct1.ToMyStruct<TOut>()

+0

有沒有辦法在轉換運算符中執行此操作?所以客戶端代碼不必顯式調用特定的方法? –

2

C#沒有泛型轉換運算符的概念;任何轉換運算符(無論是隱式還是顯式)都必須導入或導出由定義類型的泛型參數完全定義的類型。這意味着Foo<T>可以定義從Bar<T>(或反之亦然)定義的轉換運算符,並且Foo<T,U>可以定義轉換爲或來自Bar<U>的轉換,但反之亦然。這也意味着Foo<T>可以定義來自「Bar」的轉換,但反之亦然。不幸的是,沒有辦法擁有一個轉換運算符,它可以導入或導出具有泛型類型參數的類型,超出定義類型的參數,即使這些參數會受到鑄造成功的限制。

這一切意味着,必須經常使用方法而不是運算符來執行轉換(或者就此而言,執行混合類型的操作)。方法的泛型類型解析非常聰明(至少如果有人願意包含一個默認的空虛參數),但對於運算符來說它非常有限。順便說一句,如果結構使用泛型類型參數的唯一目的是定義該類型的公共字段,理論上應該可以使這樣的結構支持協方差而不用考慮結構是否是「可變的「,因爲將KeyValuePair<FordFocus,SiameseCat>分配給KeyValuePair<Vehicle,Animal>將代表FordFocusVehicleSiameseCatAnimal的分配,兩者都是類型安全的。然而,這種方法失敗了,因爲所有盒裝結構總是可變的,而且類型的可變方面不能安全地支持協方差。

2

我做了工作,使用以下方法:

public static implicit operator MyStruct<T>(MyStruct<X> value) 
{ 
    return new MyStruct<T>(value); 
} 

public static implicit operator MyStruct<T>(MyStruct<Y> value) 
{ 
    return new MyStruct<T>(value); 
} 

.... 

這是僅限於已知類型(X,Y,...),但讓我寫了下面的代碼:

MyStruct<X> x = new MyStruct<X>(...); 
MyStruct<Y> y = x; 
相關問題