Is there anyway to force a constraints for a generic definition to implement a "generic interface" ... that is, I want the class to support passing an interface and a generic class constraining it so that the class implements the interface. For example if I say:
MyGenericClass<IMyInterface, MyImplementation>.DoSomething();
That should be constrained so that MyImplementation implements IMyInterface
As far as I know that can be achieved by
public class Dynamic_Loader<T, S> where S: T
Now, is there anyway to also force T to be an interface?
Edit: The purpose of this was to have something like:
private static List<T> interfaceList = new List<T>();
public static List<T> InterfaceList {get { return interfaceList;}}
public static void Add(S input) { interfaceList.Add(input);}
and have the list restricted to only interfaces (since it is supposed to return implementations of certain interfaces)
Do you mean, can a constraint also be put on T like where T : interface?
If so, then no: this list pretty much covers your options.
What you have is as close as it gets, I believe.
Out of curiosity, what would be your reason for wanting to constrain T to be an interface?
Or do you mean can a constraint also be put on T for T to implement some specific interface?
If so, then yes: simply have two where clauses (e.g., where S : T where T : U).
where T: IMyOtherInterfaceForT
Example:
public class Test<T, V>
where T : V
where V : IEnumerable<int>
{
}
You could do something like this to enforce it at runtime instead of compile time.
public class Test<T> where T : class
{
public Test()
{
Type t = typeof( T );
if( !t.IsInterface )
throw new ArgumentException( "T must be an interface type" );
}
}
Related
public interface IFoo
public class Foo : IFoo
public interface ILang<T> where T:IFoo
public class Lang : ILang<Foo>
But now, I want something like this with wildcard
public class CarroMontadora<T> where T:ILang<?>
Beacause this does not work with my interface:
public class MYCLASS<T> where T:ILang<IFoo>
And this is not too smart to do, because is not so generics:
public class MYCLASS<T,U> where T:ILang<U> where U: IFoo
You will have to add another generic parameter to your new class:
public class CarroMontadora<T1, T2>
where T2 : IFoo
where T1 : ILang<T2>
{
}
Good options already listed but let me give you another one.
Have both ILang<T> AND a simple marker interface ILang - use ILang to enforce that condition and make ILang<T> : ILang
It's not flawlessly type-safe but that API is pretty clear enough that it is unlikely that someone will screw it up.
You cannot have nested constraints on generics on C# without having both type parameters as part of the class (your third example), however you can enforce this in a cleaner fashion by good old method signatures.
For example
public class CarroMontadora<T> where T: IFoo {
public CarroMontadora(ILang<T> param) {
// do stuff
}
}
Is there a way to implement constraint type parameters where T is from a base class or if T is a list containing the "base class"?
Something looking like this :
public class SomeClass<T> where T : MyBaseClass, IList<MyBaseClass>
No, you can't create generic constraint to work like OR.
And just to point that that kind of constraint would have been useless: you would not be able to use neither methods defined in BaseClass nor these from IList (because T could have been the first or the second).
No but you could have overloaded methods that take one or the other:
public class SomeClass<T> where T : MyBaseClass
{
public void Process(T instance)
{
}
public void Process(IList<T> list)
{
}
}
Why don't you implement an interface on the BaseClass and do.
public class SomeClass<T> where T : class, IBaseInterface
This also guarantees that the children are implementing the appropriate contracts that you want to expose.
On MSDN - C# Programming guide Constraints on Type Parameters, it says:
where T : interface_name
The type
argument must be or implement the
specified interface. Multiple
interface constraints can be
specified. The constraining interface
can also be generic.
Could somebody kindly explain, what it means to have a generic interface? And explain how that can be a constraint and what it provides?
A simple example and a simple explanation is highly appreciated.
Many thanks in advance : )
You can use a generic interface as a constraint. For example:
class MyClass<T> where T:IEnumerable<string>
you can even substitute the generic parameter of the type you define into your constraint:
class MyClass<T> where T:IEnumerable<T>
An example of a generic interface is IEnumerable<T>. It represents some collection you can enumerate. The type of the items in the collection is not relevant to the interface, so it allows you to specify that with a generic parameter.
You can for example create a class like this:
class Foo<T, E> where T : IEnumerable<E>
{ }
This way, the generic parameter T can only be a collection of type E. The constraining interface is generic as well. You can also do this:
class Foo<T> where T : IEnumerable<string>
{ }
In which case you're not allowing any type of collection, only collections of strings. You can go pretty crazy with this, like this:
class Foo<T> where T : IEnumerable<T>
{ }
Where T has to be some collection that contains collections of T.
One use is when you want a function or class to work generically but want to constrain which types can be used with it (so you don't have to make multiple overloads for instance).
Completely arbitrary code example:
interface IAnimal { }
interface IShape { }
class Tiger : IAnimal { }
class Wolf : IAnimal { }
class Circle : IShape { }
class Rectangle : IShape { }
public void MakeSound<T>(T animal) where T : IAnimal
{
}
public void Draw<T>(T shape) where T : IShape
{
}
This isn't actually how you would structure this type of functionality mind you :) You can use other constraints too:
public void someFunction<T>(T input) where T : IShape, new() // constraint to IShape, allow construction of new T with parameterless constructor
All in all they are useful for generic functions constrained to certain types.
The sentence only states that the constraining interface can not only be a class or interface, but a generic one too.
For instance, such a constraint is a valid one:
public class Controller<TModel,TRepository> where TRepository: Repository<TModel>{...}
In the below code "where T : WsgTypes.RouteRestriction", can I add multiple classes so that T can be of only those few classes types which I am interested of
public static T GetDetails<T>(string code) where T : WsgTypes.RouteRestriction
{
T details;
if (typeof(T) == typeof(WsgTypes.TicketType))
{
details = TicketTypeDetail.GetDetails(code) as T;
}
else if (typeof(T) == typeof(WsgTypes.RouteRestriction))
{
details = RouteRestrictionDetail.GetDetails(code) as T;
}
else
{
throw new NotSupportedException("");
}
return details;
throw new NotImplementedException();
}
It seems to me that this isn't a proper use of generics. It would be better if TicketType and RouteRestriction implemented some IDetailed.
No, generic type constraints can only specify a single base-class.
You can specify multiple interfaces, but this is "all of", not "any of".
What you ask is possible with overloading, but not with generics.
For inheritance you can have a single class with multiple interfaces.
public static T GetDetails<T>(string code) where T : WsgTypes.RouteRestriction, , IComparable
{
}
Instead you can have an interface and have multiple classes implementing it.
public interface IInterface
{}
public class Class1: IInterface
{}
public class Class2: IInterface
{}
public static T GetDetails<T>(string code) where T:IInterface
{
T instance;
// ...
return instance;
}
I'm afraid you can't. The usual way is to provide a common interface that all classes you're interested in implement. The problem is that, inside the generic body, the compiler expects a generic type parameter to be unambigous.
Well, or you could take an object as parameter and cast it at your will. But... no. Don't.
Note that instead of typeof, you could also use the is and as operators.
See this article...
http://msdn.microsoft.com/en-us/library/d5x73970.aspx
... for more information on constaints. You can add multiple constraints, and you can constrain by some interface or by some base class, but not by a list of arbitrary classes.
Here's an example of multiple constraints (from the above):
class Base { }
class Test<T, U>
where U : struct
where T : Base, new() { }
Did you try separating them like this:
public static T GetDetails<T>(string code) where T : WsgTypes.RouteRestriction, NextClass, AnotherClass, AndSoOn
{
...
}
I have an interface with a single generic type parameter:
public interface IDriveable<T> where T : ITransmission { ... }
I also have a class that has a type parameter that needs to be of that interface type:
public class VehicleFactory<T> where T : /* ??? */
There is a problem here with this declaration. I can't put "IDriveable", because that has no type parameters and doesn't match the type signature of IDriveable. But I also don't want to put IDriveable<U> either, because then VehicleFactory has to know what kind of IDriveable it's getting. I want VehicleFactory to accept any kind of IDriveable.
The proposed solution a coworker had was to use:
public class VehicleFactory<T, U> where T : IDriveable<U>
But I don't like this, since it's redundant. I have to say the "U" type twice:
var factory = new VehicleFactory<IDriveable<AllWheelDrive>, AllWheelDrive>();
What should go in the question marks?
What is VehicleFactory going to do with T? Does it actually need the constraint in order to work, or is it just for the sake of developer sanity checking?
One common way round this is to declare a non-generic interface (IDriveable) and then make your generic one extend that:
public interface IDriveable {}
public interface IDriveable<T> : IDriveable {}
public class VehicleFactory<T> where T : IDriveable
If you do want the factory to be able to do things with T, you could put any interface members from IDriveable<T> which don't care about T into the nongeneric IDriveable.
Does this work for you?
public class VehicleFactory<T, U> where T : IDriveable<U>
This will let the factory know what types the driveables are.
You can define the VehicleFactory with 2 types generics and anign one of them to the interface. something like:
public class VehicleFactory<T1,T2> where T1 : IDriveabel<T2>
I hope that ist not what you ment with the Idriveable. I guess the U is a specific type. Like String, etc.
You can shorten often used cases like this:
interface IDriveableAllWheel : IDriveable<AllWheelDrive>
{}
var factory = new VehicleFactory<IDriveableAllWheel, AllWheelDrive>();
or even
class AllWheelFactory : VehicleFactory<IDriveableAllWheel, AllWheelDrive>
{}
also see a kvb's answer in Calling Generic Property In Generic Class From Interface Implemented By Generic Class for possible workaround.