I'm used to C++ templates and realize that things work a little differently in C#. Here's what I want:
T CreateButton<T>() {
T test = T.create(...some vars...);
return test;
}
I thought maybe using a derivative constraint with a base class that has the "create" method defined would do the trick but it still won't compile.
I get this compile error: **error CS0119: Expression denotes a 'type parameter', where a 'variable', 'value' or 'type' was expected**
Is there a way to accomplish what I'm trying to do in C#?
Your problem is that you're calling T.Create as if it were a static method on the generic T. That poses two problems - first, you cannot inherit statics (which you'd have to do to restrict the type of T to a base-class that defined 'static Create' so that T.Create would compile). Second, even if you could inherit a static, somehow the base class .Create() would have to 'know' to return a T.
What you're after here is a Factory. Define a class that acts as a factory for T's, Then you can write
T test = Factory < T >.Create(... some vars ...);
This feels like it would result in a giant switch statement of sorts - based on the real type of T do the right thing. But this is where inversion-of-control and dependency-injection can help you. Define a Factory with 'plug-ins' for each type of T you need. Use IoC to inject the plug-ins into your factory.
Check out the discussion here
This should be what you're after:
class MyFactory<T> where T : new()
{
public T CreateMyStuff()
{
return new T();
}
}
You have to define and implement an interface (or a base class). You will also have to constrain for new()
. Then you can use generic constraints on it.
You can't call static methods against a generic parameter. IE: You can't call a static method on T
.
The issue is with the specific line T.Create(...)
T is a Type, not a variable, so unless the Create() method is a static method of the type, then it wont compile, and even then T doesn't know what create actually is, so you wont be able to compile the function call to begin with. If you constrain T in some manner so that the code knows that the Create() function exists, then you can do this.
Example
Assume T will always be a member or inherited member of some Base class, the function would be declared as follows:
T CreateButton<T>() where T : BusinessObjectBase
{
T test = (T)BusinessObjectBase.create(...some vars...);
return test;
}
In this case, the static function Create() is declared inside the BusinessObjectBase, and the type passed in as T is constrained to be, or be extended from, that class, guaranteeing the code that T will be able to call the Create() function.
Of course, as others have mentioned, its far easier to use the new() constraint. This allows you to simply return new T(); far less complex, but you lose whatever those parameters were from the create function.
With the exception of types which satisfy a new
constraint, there is no way to create a new object of generic type, given nothing but the type. Instead, your best bet is probably to have the method which needs to create the things accept a delegate suitable for the task.
// Suppose you need to be able to create things whose constructors should take // an Int32. Then do something like: void MakeLotsOfTs<T>(Func<Int32, T> CreationProc) // And whatever other stuff you want { ... whenever you need a new T for a given integer N, call CreationProc(N) }
If you have a class Foo
whose constructor takes an Int32
, and you wish to pass it to the above method, use
MakeLotsOfTs<Foo>( (Int32 param) => new Foo(param) );Note that this approach will work even if you want to use it with a class whose constructor requires something else (e.g. one could do something like:
MakeLotsOfTs<Bar>( (Int32 param) => new Bar(String.Format("Bar #{0}", param)) );
This approach requires a little more work for the caller than would being able to specify a "parameterized" new
constraint, but is much more powerful.
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.