Multiple where for generic type - c#

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

Related

Collection Inheritance

I am trying to achieve the following, however I am not sure if it is even possible.
I have the following 'base' entities
public abstract class BaseObject {}
public abstract class BaseCollection <T> : ObservableCollection<T> where T : BaseObject {}
I also have
public class Obj_1: BaseObject {}
public class Obj_1_collection : BaseCollection <Obj_1>
{
public Obj_1_Method_1 () {}
}
and
public class Obj_2: Obj_1 {}
Following the same logic as Obj_1, I want to have a Obj_2_collection. I want this collection to inherit from Obj_1_collection in order to access its methods e.g. Obj_2_collection.Obj_1_Method_1(). As I have it in my mind I am trying to do something like the following (in pseudocode):
public class Obj_2_collection : Obj_1_collection<Obj_2 extends Obj_1>
meaning that the Obj_2_collection can access Obj_1_collection, however the collection object it will be of type Obj_2
You're nearly there, your only problem is that you didn't define your Obj_1_collection as a generic.
To do so, you just have to use the syntax you used for the BaseCollection<T> and restrict the type T to Obj_1
That would give :
public class Obj_1_collection<T> : BaseCollection <T> where T : Obj_1 {}
Concerning the use of generics and the inheritance, you might want to read about the in and out modifiers keyword to enable covariance and contravariance.
As a side note, here are the C# naming conventions

Generics double interface

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

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.

Partially applying generics for type constraints

I currently try to construct a generic interface that every (generic) class deriving it will have a method accepting a delegate that accepts the type parameter and returns another class of the same type, with only another type parameter.
I tried the following:
public interface GenericInterface<out T, out SomeDerived>
where SomeDerived<T> : GenericInterface<T, SomeDerived>
{
SomeDerived<NT> bind<NT>(bindee<T, NT, SomeDerived<NT>> bindFunc);
}
public delegate AnotherDerived<T2> bindee<in T1, out T2, out AnotherDerived>(T1 param)
where AnotherDerived<T2> : GenericInterface<T2, AnotherDerived>;
public class Derived<T> : GenericInterface<T, Derived>
{
Derived<NT> bind<NT>(bindee<T, NT, Derived<NT>> bindFunc);
}
But it fails to compile and I get this error:
Invalid token '<' in class, struct, or interface member declaration
What is the correct design in such case?
EDIT:
I understand the syntatic reason for the compiler errors. You cannot apply a generic type argument a parameter in a where clause.
I am asking what is the best way to mimic such behavior.
I'll go out on a limb here and say what you're trying to do here with the Generic is impossible; I'll remove if someone thinks I'm wrong.
So lets start with this
interface IFoo<T> where T : IFoo<T>{}
class Foo<T> : IFoo<T> where T : IFoo<T>{}
class Bar<T> : Foo<T> where T : IFoo<T>{}
Lets try to instanciate this;
var foo = new Foo< Bar< ....errr what now? ad infinitum...
So to fix this, you need to redesign so you're classes looks more like this:
interface IBase {}
interface IFoo<out T> where T : IBase { }
class Foo<T> : IFoo<T> where T : IBase { }
which then allows:
IFoo<IBase> foo = new Foo<Base>();
[Addendum]
You can have function level generics that let you get around problems like these...
interface IFoo<out T> where T : IBase
{
IFoo<TBind> Bind<TBind>(Action<T, TBind> bindFunc) where TBind : IBase;
}

C# Generics: What is generic constraining interface?

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

Categories

Resources