2014-10-27 94 views
1

我正在嘗試創建泛型方法。我希望調用者能夠定義兩種不同的類型。創建泛型類型實例的方法

private TableRow AddRowHelper<TROW, TCELL>(params string[] content) where TROW : TableRow where TCELL : TableCell 
{ 
    TableRow row = new TROW(); 
    foreach (var text in content) 
    { 
     TableCell cell = new TCELL(); 
     cell.Text = text; 
     row.Cells.Add(cell); 
    } 
    productsTable.Rows.Add(row); 
    return row; 
} 

上面的代碼給了我一個錯誤。因爲它沒有新的()約束」

錯誤4無法創建變量類型「TROW」的一個實例是否可以同時指定new和基本型的約束?當我已經指定爲什麼我需要一個新的約束,該類型必須從TableRow,它總是有一個new運營商獲得。

+2

想象一下像公共類ChildOfTrow類型:TROW {private ChildOfTrow(){}} – 2014-10-27 22:02:37

+0

你是什麼意思'TableRow總是有'new'運算符'? – haim770 2014-10-27 22:02:46

+1

是的,*可以指定新的和基本類型的約束:'where TROW:TableRow,new()'。 – haim770 2014-10-27 22:05:54

回答

1

它可以同時指定一個新的基地型約束。這樣做會使你的方法的簽名看起來像這樣

public TableRow AddRowHelper<TROW, TCELL>(params string[] content) 
     where TROW : TableRow, new() where TCELL : TableCell, new() 
{ 

您是基於泛型類型實例化任何時候,你必須使用new約束限制泛型類型的那些具有公共參數的構造函數。此外,創建變量類型的實例時,方法不能提供參數。

即使您已指定類型必須從TableRow派生(它總是有一個新的操作符),您仍然需要一個new約束,因爲派生類型可能沒有公共無參數構造函數,並且這將是一個將被調用的構造函數。

考慮一下:

public class A : TableRow 
{ 
    private A(){} 
} 

並認爲這是正在使用

AddRowHelper<A,TableCell>(args); 

這會導致編譯錯誤,

'A' 必須是一個非抽象類型與一個公共無參數構造函數,以便將其用作泛型類型或方法'AddRowHelper(params string [])'中的參數'TROW''

5

爲什麼我需要一個新的約束,當我已經指定的類型必須派生自TableRow,w總是有一個新的運營商。

TROW可能是從TableRow繼承並沒有一個類型的默認公共constructor.That就是爲什麼你需要添加一個new()約束。

3

默認的無參數構造函數可以被派生類隱藏。因此,new()約束不能從基類繼承。

樣品:

public class TableRow 
{ } // implements a default, parameterless constructor 

public class DeivedRow : TableRow 
{ 
    public DerivedRow(string s) 
    { } // no parameterless constructor 
}