Generics double interface - c#

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

Related

extend a class to conform to an interface?

I have an interface:
interface IFoo {
int foo(int bar);
}
Can I now extend an existing class to conform to the interface? Say class String. I know I can define the foo() method on strings. But is it possible to go further and tell the compiler that strings can be cast to IFoo?
You can do it with other classes, but not with System.String, because it is sealed.
If you wanted to do this to a non-sealed class, you could simply derive from it, add appropriate constructors, and put the interface as something that your new class implements.
interface IFoo {
int Size {get;}
}
// This class already does what you need, but does not implement
// your interface of interest
class OldClass {
int Size {get;private set;}
public OldClass(int size) { Size = size; }
}
// Derive from the existing class, and implement the interface
class NewClass : OldClass, IFoo {
public NewCLass(int size) : base(size) {}
}
When the class is sealed, your only solution of presenting it as some interface through composition: write a wrapper class implementing your interface, give it an instance of the sealed class, and write method implementations that "forward" calls to the wrapped instance of the target class.
I think the question could be restated as, 'can I use extension methods to make a sealed class implement an interface that it did not before?' As others point out, the String class is sealed. However, I think you have to name what interfaces a class implements in its declaration:
public someClass : IFoo
{
// code goes here
}
So you can't do this directly to String, not just because it is sealed, but because you do not have the source code for it.
The best you can do is make your own class that has-a String and use it like a string. Anything that a String does that you need to do you will either have to do on its String member (thus making it public), or you will have to wrap/reimplement the method you need:
public class betterString : IFoo
{
public String str {get; set;}
public foo(int i)
{
// implement foo
}
}
then later, when using it:
public void someMethod(betterString better)
{
better.foo(77);
System.Console.WriteLine(better.str);
}

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.

Force generic interface implementation in C#

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" );
}
}

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