简体   繁体   中英

Method to Create Instance of Generics Type

I'm trying to create a generics method. I want the caller to be able to define two different types.

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;
}

The code above gives me an error.

Error 4 Cannot create an instance of the variable type 'TROW' because it does not have the new() constraint"

Is it possible to specify both a new and base-type constraint? And why do I need a new constraint when I have specified that the type must derive from TableRow , which always has a new operator.

Why do I need a new constraint when I have specified that the type must derive from TableRow, which always has a new operator.

Well TROW might be a type that inherits from TableRow and doesn't have a default public constructor.That's why you need to add a new() constraint.

The default, parameterless constructor can be hidden by a deriving class. Hence, the new() constraint can't be inherited from the base class.

Sample:

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

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

It is possible to specify both a new and base-type constraint. Doing that would make your method signature look like this

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

Any time you are instantiating based on a generic type, you must use the new constraint to restrict the generic types to those which have a public parameterless constructor. Further, a method cannot provide arguments when creating an instance of a variable type.

You need a new constraint even though you have specified that the type must derive from TableRow ( which always has a new operator ) because the derived type may not have a public parameterless constructor, and that is the one which would be called.

Consider this:

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

And consider it being used

AddRowHelper<A,TableCell>(args);

This will cause a compilation error,

'A' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'TROW' in the generic type or method 'AddRowHelper(params string[])'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM