Working with Generic classes with different constraints - c#

I have two legacy C# user controls I need to work together.
I have an existing dialog onto which I need to add an existing generic usercontrol.
I have tried to sample the hierarchy below
interface Foo<T> {}
interface Bar<T>
{
T DataObject { get; set; }
}
public class ClassA<T> where T : Foo<T>
{
public ClassA(T dataObject)
{
//Do stuff if T implements Bar<T> - Pseudocode ahead
if(var T is Bar<T>)
{
var x = new ClassB<T>();
//x is typesafe, and I can set DataObject
x.DataObject = dataObject;
}
}
}
public class ClassB<T> where T : Bar<T>
{
T DataObject { get; set; }
}
The existing dialog, ClassA currently don't have any generic contraints, but could easily be changed to require T implementing Foo<T>.
The userControl, ClassB is based on another interface, Bar<T>. In practice, Bar<T> objects always implements Foo<T> - in theory of course not.
Are there any construction I can use to declare an object of type ClassB, and get compile time validation?
The construction above will give me a compile error stating:
The type 'T' cannot be used as type parameter 'T' in the generic type
of method ClassB<T>. There is no implicit reference conversion from
'T' for Bar<T>
I can make the ClassB object with Reflection, setting the properties using Reflection as well - but I would prefer a compile time solution.
But in my current situation with two existing dialogs - i'm not sure I am able to.
Any help is appreciated - also just if it is stating what I expect, that it can't be done.
--EDIT
Trying to elaborate a bit.
The problem rises when I have a ClassC that implements both Foo<T> and Bar<T>
public class ClassC<T> : Foo<T>, Bar<T>
{
T DataProperty
}
If I make an instance of ClassA<ClassC>, that is T in the specific instance is ClassC - then is there a way in code I can use T in creating an instance of ClassB- in this case T in ClassA does live up to the ClassB constraints, since T is ClassC.
I havent figured out how or if possible - tend to believe I can't.
As I wrote above, I have a solution based on reflection, i'm just not fan of using reflection and getting run-time validation only. But in this case with two legacy objects that need to work together I might be running out of options.

First of all, your types are a bit weird. They are kind-of recursive, with ClassB<T> requiring a T that implements Bar<T> which has the same structure as ClassB<T>. Maybe you meant to ClassB<T> to implement Bar<T> instead of requiring it as a type parameter?
Anyway you cannot do this. In order to be able to write ClassB<T>, the compiler needs to ensure that T is a valid type parameter for ClassB<> at runtime. This can only be the case when the type parameters on ClassA<T> for T are at least as restrictive as the ones from ClassB<T>.
Unfortunately, even a hard type check which would ensure that this is the case will not allow you to write ClassB<T>.
So without being able to write ClassB<T>, you will not be able to get static type safety at compile-time. So even when you create an instance of ClassB<T> (which you can), you won’t be able to access DataProperty on it since you will not be able to cast it as a ClassB<T>.
So in order to solve this, you would either have to access DataProperty using reflection only, or call a method inside ClassA<T> that does have the type constraint. I’ll show you both solutions:
public class ClassA<T>
where T : Foo<T>
{
public ClassA(T dataObject)
{
if (typeof(Bar<T>).IsAssignableFrom(typeof(T)))
{
// method 1, calling a generic function
MethodInfo mi = typeof(ClassA<T>).GetMethod("SetBDataObject").MakeGenericMethod(typeof(Bar<T>));
mi.Invoke(this, new object[] { dataObject });
// method 2, doing it all with reflection
Type type = typeof(ClassB<>).MakeGenericType(typeof(T));
object x = Activator.CreateInstance(type);
type.GetProperty("DataObject").SetValue(x, dataObject);
}
}
public object SetBDataObject<TB> (TB obj)
where TB : Bar<TB>
{
var x = new ClassB<TB>();
x.DataObject = obj;
return x;
}
}

The first thing that probably is confusing in your code, is that you have used the same letter T as the Type parameter in both classes ClassA<T> and ClassB<T>.
I'll start by stating the obvious:
when you call var x = new ClassB<T>(); the constraint for T here is in the context of ClassA<T> (i.e. T : Foo<T>), while new ClassB<T>() expects T to match the constraint of T : Bar<T>.
It seems to me that underlying reason for the issue you are having is a design problem. It looks like you a little mix up between types and classes.
Lets walk it through:
from the Gang of Four Design Patterns book:
An objects's class defines how the object is implemented .The class
defines object's internal state and the implementation of its
operations.
In contrast, an objects's type only refers to its interface -the set
of requests to which it can respond.
An object can have many type, and object of different classes can have
the same type.
The usage of interfaces in your code implies coding against types (that's good!).
Checking for if (dataObject is Bar<T>) and upon the result constructing a ClassB<U> where !typeof(U).Equals(typeof(T) implies heavily relying on implementation (e.g. class).
If you ask me, I think you should try one of the following:
Use the factory pattern for constructing ClassB. In the dedicated factory you can add some more logics and verifications in order to decide how to construct it (from your code, it is not clear since the types do not match...).
If possible, resolve the relation between Foo<T> and Foo<T> and declare the constraints in the interfaces. In that case, both interfaces should have same constraints fto T

Related

Issue with List of generic classes

So I've got a generic class called VariableSeries, an abstract class called Indicator derived from it, and then various classes (let's call them indicators) that implement that abstract class. I want to have a List of indicators and be able to use it.
public class VariableSeries<T>
{
protected List<T> Series;
public int CurrentBar { get; private set; }
public T this[int index]
{
get
{
if (index > CurrentBar)
throw new Exception("Tried to look too far in the past, data does not exist.");
return Series[CurrentBar - index];
}
}
...
}
And I've got an Indicator class that's derived from VariableSeries:
public abstract class Indicator<T> : VariableSeries<T>
{
...
}
Now I want to have a List of indicators of various types. My first idea was to just declare a List, but that doesn't really work. And I can't just throw an interface at it and cast to that, because I need to use the indexation, which makes use of the generic type.
So let's say I've got the following indicator (one of many):
public class MovingAverage<T> : Indicator<double>
{
...
}
Is there any way to do the following:
List<???> Indicators = new List<???>();
Indicators.Add(new MovingAverage<type is provided dynamically>());
do stuff with Indicators[0][0];
Perhaps some sort of way of casting to a generic class without having to specify the type, like ((VariableSeries<>)Indicators[0])[0]?
The ??? in your List<???> must be a concrete type. This concrete type must, in your case, a commonly shared basetype or interface.
All your classes share a basetype VariableSeries<T> but this one is not concrete / specific. So List<VariableSeries<T>> is not possible.
If all your indicaters would use the generic type double, than you could use List<VariableSeries<double>>, but I am afraid that is not the case.
The question is: what are your going to do with that list? Iterate through them and then what? Ask for their value? What value? What type? A double? A string? The compiler cannot know!
One solution could be to create an interface like this:
public interface IVariableSeries
{
object this[int index] { get; }
}
Implement this interface EXPLICITLY in your VariableSeries<T> and use this interface as your concrete type in your list: List<IVariableSeries>.
You can make the abstract class implement an interface with all methods that will be common to all classes and has no type parameters.
class VariableSeries<T> : IUntypedInterface
Then you can use a List<IUntypedInterface> to get then all together.
You can do some stuff using reflection. For example you can create a MovingAverage with a dynamic T using the following:
Type dynamicType = typeof(int); // or any other, e.g. user selected type
var instance = (dynamic)Activator.CreateInstance(typeof(MovingAverage<>).CreateGenericType(dynamicType));
The problem of course is that you don't know the type of instance at compile time. Thus you can't call any methods on it and you can't cast it of course the type isn't known at compile time. That's why I wrapped it as dynamic. You can call any method and it will in the background reflect into that type and look for the method signature that you called.
You can check if instance is a MovingAverage<> by doing
typeof(MovingAverage<>).Equals(instance.GetType().GetGenericTypeDefinition())
Be aware that this will return false when instance is actually of a derived type of MovingAverage. You can also check that, but it's a bit more complicated.
Going the dynamic route is of course a dangerous path in a language that otherwise relies so much on static type checking. You won't have refactoring support and you will have to test a lot running your code. A single typo and your program will throw an exception.
Also, I would suggest you get familiar with .Net reflection. You're entering a dangerous world.
Add a generic method and pass the type to that method. this code will go in generic method.
List Indicators = new List();
Indicators.Add(new MovingAverage());

How to create a generic interface of a method that returns a Type of a class that implements an interface?

I'm looking for a way to define "MethodA" below, such that it returns a class definition (System.Type), of which an instance of said type implements "InterfaceB"
interface IMyInterface
{
TType MethodA<TType, TInterface>()
: where TType : System.Type
: where [instanceOf(TType)] : TInterface
}
(Note: instanceOf is not real, of course...)
I suspect it's not possible to get this kind of verification at compile time. I'm hoping someone out there will prove me wrong.
Thanks in advance for any guidance.
EDIT: I've updated this in hopes of being more specific that what is returned is a System.Type, of which this later code can execute:
var classType = myInterface.MethodA<(something, ISomeInterface)>();
ISomeInterface = new classType(); //--Assuming default constructor
I haven't really focused on this part yet, just more curious about the theoretical construction of my primary quesiton.
There are two interpretations of your question; one would be trivial, one impossible, so I'll go forward and cover both.
You want to return an instance of a type which implements both System.Type and TInterface.
This is trivial: Just use where TType : Type and where TType : TInterface.
You want to return an instance of System.Type that represents a type which inherits from TInterface.
This is impossible to specify in the .NET (and C#) type-system.
The type system can only resolve information from the type hierarchy themselves, but not enforce "contracts" like restricted run-time property values. There are a few hacks regarding default-constructors etc., but as far as I know not even testing for existing methods is possible (unlike C++ templates, for instance, not to speak of Qi et al.).
Update
Please check the comment from Michael Graczyk.
Also: I just found out that there are code-contract checkers (static and run-time) for .NET: Microsoft DevLabs Code-Contracts for .NET. I have never used them, not even new about them, but that looks interesting!
However, even without looking, I'm quite sure that overload-resolution etc. will not be able to use such information.
In this situation:
// We have an interface...
interface InterfaceB {}
// And this class implements the interface.
class ImplementsB : InterfaceB {}
// But this class does not.
class DoesNotImplementB {}
You could define MethodA as:
static Type MethodA<TClass, TInterface>()
where TClass : TInterface
{
return typeof(TClass);
}
Then the following will work:
Type t = MethodA<ImplementsB, InterfaceB>();
But this gives a compile-time error:
Type t = MethodA<DoesNotImplementB, InterfaceB>();
The type 'DoesNotImplementB' cannot be used as type parameter 'TClass' in the generic type or method 'MethodA<TClass,TInterface>()'. There is no implicit reference conversion from 'DoesNotImplementB' to 'InterfaceB'.
So, this way you are sure that the result of MethodA is a Type of a class that implements TInterface. Given that Type object, you can instantate it later like this:
public object Instantiate(Type type)
{
// Call the default constructor.
// You can change this to call any constructor you want.
var constructor = type.GetConstructor(Type.EmptyTypes);
var instance = constructor.Invoke(new object[0]);
return instance;
}
If you know that your Type is compatible with some interface TInterface, then you can avoid a cast with an additional method like this:
public TInterface Instantiate<TInterface>(Type type)
{
return (TInterface)Instantiate(type);
}
However, if type is a Type that somehow does not implement TInterface, you'll get an InvalidCastException at run-time. There is no way to constrain Type to be a type that implements a particular interface at compile-time. However, at run-time you can check it to avoid the InvalidCastException exception:
public TInterface Instantiate<TInterface>(Type type)
{
if (!typeof(TInterface).IsAssignableFrom(type))
throw new Exception("Wrong type!");
return (TInterface)Instantiate(type);
}
Note that typeof(TType) is an expression that results in a Type object, so everywhere you see typeof() you could replace it with any Type variable and vice versa.
Is this what you wanted to know?

c# generics on a method with the constraint that the type must be of "this" type

I have a C# class hierarchy with a common base type and two derived types. I want to declare an abstract method on the base class something like this :
public abstract IEnumerable<T> GetSiblings<T>() where T : MyBaseClass
... and I want this method to be implemented in the derived classes such that T is the type of that derived type, for each of the derived types, ie, in derived class A:
public override IEnumerable<A> GetSiblings<A>() { ... }
... and in derived class B ...
public override IEnumerable<B> GetSiblings<B>() { ... }
Put another way, each derived class must implement the method so that it returns an IEnumerable of items of the same type. Is there any way to implement this in C# ?
Well, you can hardly call a method generic if it only accepts a parameter of a single type, and your method signatures will have different return types which isn't allowed. Why don't you define an interface for all of these classes and simply return an IEnumerable<IMyClass>?
You can't do this because the return types are different. Simple as that. The reason is if you create an instance of A and stuff it into your base class(cast it) then the return type will be wrong.
You might be able to to use new instead but that might break your hierarchy.
This is not supported by the type system. It's a common enough problem, represented often as
class Animal<T> where T : Animal<T> { }
class Cat : Animal<Cat> { } // what you desire
class Dog : Animal<Cat> { } // what is possible yet not desired
But not a problem that has as yet been acted upon by the appropriate parties (be it the framework providers or C# team, not sure who).
Until it passes the critical "worth it" test as determined by costs (and opportunity costs) versus benefits, you'll have to work around it.
I found the solution. Apparently in C# 4.0, generic parameter types can be covariant, so what I've posted above will work. C# 3.5 or lower, and it doesn't work. Took a lot of Googling.

Factory Pattern: Enums or Types?

When implementing a factory or simple factory, what would go against using a Type instead of an Enum to specify the class to instantiate?
For example
public class SimpleFactory
{
public static ITest Create(Type type)
{
if (type == typeof(ConcreteTest1))
return new ConcreteTest1();
if (type == typeof(ConcreteTest2))
return new ConcreteTest2();
throw new Exception("Invalid type");
}
}
Using an enum is more restrictive, which means that it is less likely that the user will try to use your factory with an unsupported type.
I find that it's good to do everything possible when defining an API to discourage usage patterns that will cause exceptions to be thrown. Allowing "Type" in this case opens up millions of ways to call your function that will result in:
throw new Exception("Invalid type");
Using an enum would eliminate this. The only way an enum would throw would be if the user did something noticably wrong.
Factories are only useful if they perform configuration or initialization on your objects to put them in a valid state. I wouldn't bother with a factory if all it does is new up and return objects.
I would create a factory for each class hierarchy. For example:
public abstract class Vehicle {}
public class Car : Vehicle {}
public class Truck : Vehicle {}
public class VehicleFactory
{
public Vehicle CreateVehicle<T>() where T : Vehicle
{
// Get type of T and delegate creation to private methods
}
}
if you want a fool proof factory you must create one concrete factory for each concrete type. This class doesn't follow open-closed principle: each time you got a new concrete type you've to re-edit this class.
IMHO a better approach is using inheritance, one concrete factory class for each concrete type.
I would prefer to use a generic constraint, for the reason that having an enum just to specify what kind of object you want seems redundant to me, and with using a type as you've described you violate the Open/Closed principle. What I would do differently from what you have done there is constrain your type so that only allowable types can be passed in.
I'll give an example in c# using generics.
public class SimpleFactory
{
public static ITest Create<T>()
where T: ITest, new()
{
return new T();
}
}
Then you would implement IConcreteTest with both ConcreteTest1 and ConcreteTest2 and you could use your factory like this:
ConcreteTest1 test1 = SimpleFactory.Create<ConcreteTest1>();
If you want to create by type, you could just use Activator.CreateInstance(Type t). Wrap it in a template method to limit it to your interface, something like Create<T> where T:ITest.
I think the biggest concern that I would have is that the purpose of the factory is to allow client code to create a derived instance of an object without knowing the details of the type being created (more specifically, the details of how to create the instance, but if done correctly, the caller should not need to know any of the finer details beyond what is provided by the base class).
Using type information extracted from the derived type still requires the caller to have some intimate knowledge about which type he wants to instantiate, which makes it difficult to update and maintain. By substituting an Enum type (or string, int, etc.), you can update the factory without having to update the calling code to be aware of the new derived types.
I suppose one might argue that the type name could be read in as a string from a config file, database, etc., and the type information determined using Reflections (in .NET) or RTTI (in C++), but I think this is a better case for simply using the type string as your identifier since it will effectively serve the same purpose.

How can you require a constructor with no parameters for types implementing an interface?

Is there a way?
I need all types that implement a specific interface to have a parameterless constructor, can it be done?
I am developing the base code for other developers in my company to use in a specific project.
There's a proccess which will create instances of types (in different threads) that perform certain tasks, and I need those types to follow a specific contract (ergo, the interface).
The interface will be internal to the assembly
If you have a suggestion for this scenario without interfaces, I'll gladly take it into consideration...
Not to be too blunt, but you've misunderstood the purpose of interfaces.
An interface means that several people can implement it in their own classes, and then pass instances of those classes to other classes to be used. Creation creates an unnecessary strong coupling.
It sounds like you really need some kind of registration system, either to have people register instances of usable classes that implement the interface, or of factories that can create said items upon request.
You can use type parameter constraint
interface ITest<T> where T: new()
{
//...
}
class Test: ITest<Test>
{
//...
}
Juan Manuel said:
that's one of the reasons I don't understand why it cannot be a part of the contract in the interface
It's an indirect mechanism. The generic allows you to "cheat" and send type information along with the interface. The critical thing to remember here is that the constraint isn't on the interface that you are working with directly. It's not a constraint on the interface itself, but on some other type that will "ride along" on the interface. This is the best explanation I can offer, I'm afraid.
By way of illustration of this fact, I'll point out a hole that I have noticed in aku's code. It's possible to write a class that would compile fine but fail at runtime when you try to instantiate it:
public class Something : ITest<String>
{
private Something() { }
}
Something derives from ITest<T>, but implements no parameterless constructor. It will compile fine, because String does implement a parameterless constructor. Again, the constraint is on T, and therefore String, rather than ITest or Something. Since the constraint on T is satisfied, this will compile. But it will fail at runtime.
To prevent some instances of this problem, you need to add another constraint to T, as below:
public interface ITest<T>
where T : ITest<T>, new()
{
}
Note the new constraint: T : ITest<T>. This constraint specifies that what you pass into the argument parameter of ITest<T> must also derive from ITest<T>.
Even so this will not prevent all cases of the hole. The code below will compile fine, because A has a parameterless constructor. But since B's parameterless constructor is private, instantiating B with your process will fail at runtime.
public class A : ITest<A>
{
}
public class B : ITest<A>
{
private B() { }
}
Juan,
Unfortunately there is no way to get around this in a strongly typed language. You won't be able to ensure at compile time that the classes will be able to be instantiated by your Activator-based code.
(ed: removed an erroneous alternative solution)
The reason is that, unfortunately, it's not possible to use interfaces, abstract classes, or virtual methods in combination with either constructors or static methods. The short reason is that the former contain no explicit type information, and the latter require explicit type information.
Constructors and static methods must have explicit (right there in the code) type information available at the time of the call. This is required because there is no instance of the class involved which can be queried by the runtime to obtain the underlying type, which the runtime needs to determine which actual concrete method to call.
The entire point of an interface, abstract class, or virtual method is to be able to make a function call without explicit type information, and this is enabled by the fact that there is an instance being referenced, which has "hidden" type information not directly available to the calling code. So these two mechanisms are quite simply mutually exclusive. They can't be used together because when you mix them, you end up with no concrete type information at all anywhere, which means the runtime has no idea where to find the function you're asking it to call.
So you need a thing that can create instances of an unknown type that implements an interface. You've got basically three options: a factory object, a Type object, or a delegate. Here's the givens:
public interface IInterface
{
void DoSomething();
}
public class Foo : IInterface
{
public void DoSomething() { /* whatever */ }
}
Using Type is pretty ugly, but makes sense in some scenarios:
public IInterface CreateUsingType(Type thingThatCreates)
{
ConstructorInfo constructor = thingThatCreates.GetConstructor(Type.EmptyTypes);
return (IInterface)constructor.Invoke(new object[0]);
}
public void Test()
{
IInterface thing = CreateUsingType(typeof(Foo));
}
The biggest problem with it, is that at compile time, you have no guarantee that Foo actually has a default constructor. Also, reflection is a bit slow if this happens to be performance critical code.
The most common solution is to use a factory:
public interface IFactory
{
IInterface Create();
}
public class Factory<T> where T : IInterface, new()
{
public IInterface Create() { return new T(); }
}
public IInterface CreateUsingFactory(IFactory factory)
{
return factory.Create();
}
public void Test()
{
IInterface thing = CreateUsingFactory(new Factory<Foo>());
}
In the above, IFactory is what really matters. Factory is just a convenience class for classes that do provide a default constructor. This is the simplest and often best solution.
The third currently-uncommon-but-likely-to-become-more-common solution is using a delegate:
public IInterface CreateUsingDelegate(Func<IInterface> createCallback)
{
return createCallback();
}
public void Test()
{
IInterface thing = CreateUsingDelegate(() => new Foo());
}
The advantage here is that the code is short and simple, can work with any method of construction, and (with closures) lets you easily pass along additional data needed to construct the objects.
Call a RegisterType method with the type, and constrain it using generics. Then, instead of walking assemblies to find ITest implementors, just store them and create from there.
void RegisterType<T>() where T:ITest, new() {
}
I don't think so.
You also can't use an abstract class for this.
I would like to remind everyone that:
Writing attributes in .NET is easy
Writing static analysis tools in .NET that ensure conformance with company standards is easy
Writing a tool to grab all concrete classes that implement a certain interface/have an attribute and verifying that it has a parameterless constructor takes about 5 mins of coding effort. You add it to your post-build step and now you have a framework for whatever other static analyses you need to perform.
The language, the compiler, the IDE, your brain - they're all tools. Use them!
No you can't do that. Maybe for your situation a factory interface would be helpful? Something like:
interface FooFactory {
Foo createInstance();
}
For every implementation of Foo you create an instance of FooFactory that knows how to create it.
You do not need a parameterless constructor for the Activator to instantiate your class. You can have a parameterized constructor and pass all the parameters from the Activator. Check out MSDN on this.

Categories

Resources