C# Generics: What is generic constraining interface? - c#

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>{...}

Related

.NET Core Cast to interface with generic type parameter of type which implements interface

In .NET Core C#
I' trying something like this:
(IInterface<IParameter>)instance
Where instance is new Implementation<Parameter>()
And Implementation : IInterface & Parameter : IParameter
The issue is with the casting of the generic parameter. When I provide Parameter instead of IParameter it works but at compile time there is no way to know which type that implements IParameter will be used. All of these objects will be created via reflection.
So is there any way this cast works? Or some other way to implement this like providing no generic type parameter like you can with typeof.
EDIT Thanks to Ziriax
A Fully Working Example:
interface IInterface
{
void Run(TInput input);
}
abstract class AbstractClass<TInput> : IInterface
where TInput : IParameter
{
public abstract void Execute(TInput input);
public void Run(IParameter input)
{
Execute((TInput)input);
}
}
interface IParameter {}
class Implementation : AbstractClass<Parameter>
{
public void Run(Parameter input)
{
}
}
class Parameter : IParameter {}
class Program
{
static void Main()
{
object instance = new Implementation();
var castInstance = (IInterface) instance;
castInstance.Run(new Parameter());
}
}
Why don't you add a non-generic interface too:
interface IInterface
{
void Run(IParameter input);
}
And then let your generic interface extend this non-generic one.
Obviously your implementations should cast the IParameter, someone needs to cast it... You could make an abstract base class that does this for you, so not every implementation has to do this.
You might also be interested in the double dispatch pattern, although I'm not sure this will work in your case.
As you have it now, this cannot work. Your Implementation class implements IInterface<Parameter>, so its Run method only accepts a parameter of the concrete Parameter type, whereas the IInterface<IParameter> requires that its Run method accepts an instance of any type that implements IParameter.
If the type of cast you're trying to do were allowed, I could define a different class that implements IParameter, e.g.:
public class DifferentParameter : IParameter { ... }
And then do:
castInstance.Run(new DifferentParameter());
But your Implementation's Run method can't take DifferentParameter!
.NET therefore prevents you from performing the cast itself.
There are situations in which this kind of cast is allowed - if your interface were instead to be defined as:
interface IInterface<out TOutput>
where TOutput : IResult
{
TOutput Run();
}
By making the generic parameter out, it makes the interface covariant. This restricts the use of the type parameter as the result of method calls, but for covariant interfaces, casts like yours are allowed.
You can find plenty of documentation on both covariance and contravariance in the .NET documentation.

Constraints on Type Parameters for object and list of objects

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.

Multiple interfaces contained in one List<T>

Is there a way to define the type in a generic class like List to have contain objects which only implent multiple interfaces? Possibly class type and interfaces.
For example:
List<myObjectBase, IDisposable, IClonable> myList;
Not sure if I understood correctly, but how about this:
class MyList<T> : List<T>
where T : myObjectBase, IDisposable, IClonable
{
}
This way you can only add objects to the list which derive from the base and implement those interfaces.
No. In that case you would have to express that in the following way:
public class CommonStuff : MyObjectBase, IDisposable, IClonable {}
Then you can write:
List<CommonStuff> myList;
No, multiple generic parameters are not supported.
It wouldn't make much sense either. There would be no benefit of using the generic List<T> class over something like an ArrayList. You would lose all of the type safety benefits and you'd wind up still having to cast things all over the place.
The better option would be to create a composite class that handles all of the things you want to do...and then use that:
public class CommonBase : MyBaseClass, ICloneable, IDisposable
{
}
And then use that as your generic parameter:
var newList = new List<CommonBase>();
One approach that may be helpful is to define an interface ISelf<out T> whose one member, Self, simply returns "this" as a T; then for any interface IWhatever that might be combined, define a generic version IWhatever<out T> which inherits both the IWhatever and ISelf<T>. In that case, a class Whizbang which implements IFoo<Whizbang> and IBar<Whizbang> will implicitly implement ISelf<Whizbang>, IFoo<IBar<Whizbang>>, IBar<IFoo<Whizbang>>, etc. A routine which needs something that implements both IFoo and IBar can accept a parameter of type IFoo<IBar>; that parameter will implement IFoo; its Self property will implement IBar. Any object which implements multiple interfaces using this pattern may be cast to a nested interface type of the given form using some or all of the interfaces, listed in any order.
Below is the simplest solution for adding multiple interfaces that worked for me.
List<ICommonInterface> myList = new List<ICommonInterface>()
myFirstClass m1C = new myFirstClass();
mySecondClass m2C = new mySecondClass();
myList.Add(m1C);
myList.Add(m2C);
foreach (var item in myList)
{
item.Clone();
item.Dispose();
}
class myFirstClass : ICommonInterface
{
// implement interface methods
}
class mySecondClass : ICommonInterface
{
// implement interface methods
}
interface ICommonInterface : IDisposable, IClonable
{
}
interface IDisposable
{
void Dispose(){}
}
interface IClonable
{
void Clone(){}
}
You can use an ArrayList and can check the Type of an object in this list - maybe it is handier.
if(list[i] is Type)

Multiple where for generic type

I need to specify that a generic type for my class implements an interface, and is also a reference type. I tried both the code snippets below but neither work
public abstract class MyClass<TMyType>
where TMyType : IMyInterface
where TMyType : class
public abstract class MyClass<TMyType>
where TMyType : class, IMyInterface
I'm unable to specify multiple where clauses for a type, is it possible to do this?
A question about how to define multiple where clauses links here as a duplicate. If that question truly is a duplicate than this "complete" answer must contain both cases.
Case 1 -- Single generic has multiple constraints:
public interface IFoo {}
public abstract class MyClass<T>
where T : class, IFoo
{
}
Case 2 -- Multiple generics each with their own constraints:
public interface IFoo1 {}
public interface IFoo2 {}
public abstract class MyClass<T1, T2>
where T1 : class, IFoo1
where T2 : IFoo2
{
}
The latter syntax should be fine (and compiles for me). The first doesn't work because you're trying to provide two constraints on the same type parameter, not on different type parameters.
Please give a short but complete example of the latter syntax not working for you. This works for me:
public interface IFoo {}
public abstract class MyClass<T>
where T : class, IFoo
{
}

Declaring inherited generics with complex type constraints

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.

Categories

Resources