Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to constrain generic type to must have a construtor that takes certain parameters?

I have a wrapper generic class that intended to be used with a set of types. Those types are generated by a utility and are all derived from a base class ClientBase. While ClientBase has only a default constructor, all generated types have default constructor as well as a constructor takes a string as parameter. In the constructor of the wrapper class, I instantiate an instance of the type with the constructor that takes a string. Here is a sample code:

public class ClientBase
{ }

public class GenericProxy<T>
    where T: ClientBase, new()
{
    T _proxy;

    public GenericProxy(string configName)
    {
        _proxy = new T(configName);    
    }
}

This code does not compile because type T is not guaranteed to have a constructor that takes a string. Is there a way to define a constrain on the generic class to enforce that the type T must have a constructor that take a string? If this is not possible, what are good alternatives to handle this kind of situation?

like image 819
Hongwei Yan Avatar asked May 12 '09 16:05

Hongwei Yan


People also ask

How to specify a generic parameter as a constraint?

You can also specify a generic parameter as a constraint. The type argument supplied for the type you're constraining must be or derive from the type of the constraint. This parameter is called a naked type constraint.

How to use type parameters in generic constraints in typescript?

Using type parameters in generic constraints TypeScript allows you to declare a type parameter constrained by another type parameter. The following prop () function accepts an object and a property name. It returns the value of the property.

Does the entry class have a generic constructor?

Although the Entry class isn't generic, it has a generic constructor, as it has a parameter element of type E. The generic type E is bounded and should implement both Rankable and Serializable interfaces. Now, let's have a look at the Rankable interface, which has one method:

What is the purpose of the new() constructor constraint?

The new () constructor constraint enables you to instantiate an object of a generic type. Normally, you cannot create an instance of a generic type parameter. The new () constraint changes this because it requires that a type argument supply a public parameterless constructor.


Video Answer


2 Answers

It's not possible. I'd like to see "static interfaces" to handle this, but don't expect them any time soon...

Alternatives:

  • Specify a delegate to act as a factory for T
  • Specify another interface to act as a factory for T
  • Specify an interface on T itself for initialization (and add a constraint so that T implements the interface)

The first two are really equivalent. Basically you'd change your proxy class to something like this:

public class GenericProxy<T>
    where T: ClientBase, new()
{
    string _configName;
    T _proxy;
    Func<string, T> _factory;

    public GenericProxy(Func<string, T> factory, string configName)
    {
        _configName = configName;
        _factory = factory;
        RefreshProxy();
    }

    void RefreshProxy() // As an example; suppose we need to do this later too
    {
        _proxy = _factory(_configName);
    }
}

(I assume you're going to want to create more instances later - otherwise you might as well pass an instance of T into the constructor.)

like image 164
Jon Skeet Avatar answered Nov 02 '22 21:11

Jon Skeet


Unfortunately what you're trying to do isn't possible.

MSDN article on Type Constraints

like image 36
Joseph Avatar answered Nov 02 '22 20:11

Joseph