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());
Related
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
I'm looking for a way to get wildcards to work in .NET generics.
My code is as follows:
private class Rule<TSource, TSelected> where TSource : class where TSelected : class
{
// stuff in here
}
I want to be able to create a List<> of Rules where the TSource will be the same but the TSelected may be different.
You need to make a contravariant generic interface IRule<TSource, in TSelected> and make a list of that, where in addition TSelected is going to be constrained to some meaningful class. Constraining to any reference type as in your existing code will compile, but you won't be able to do anything meaningful with anything that has to do with TSelected.
At this time there is no other way to use variant generics (unless of course you go into reflection mode with List<dynamic> or something equivalent), so if this solution does not work for you you will need to redesign.
If I read your question right, I think you'd have to do this:
public interface ISelected
{
// ISelected interface
}
// A TSelected implementation
public class Implementation1: ISelected { }
// Another
public class Implementation2 : ISelected { }
// our Rule
private class Rule<TSource, TSelected> where TSource : class where TSelected ISelected
{
}
If the TSelected classes has the same super-class, you can just make a list of Rule<TSource, TSelectedSuperClass>. I believe you can use typeof (http://msdn.microsoft.com/en-us/library/58918ffs(v=vs.71).aspx) to get the exact subclass after reading the TSelected object again.
Alternatively you can make a container class to contain both and also store the exact types.
An interface could do it instead of a super class. If the Selected share implementation however, I prefer an abstract class.
I have an interface
public interface ITcpSerializable<T>
{
Byte[] Serialize();
T Deserialize(Byte[] data);
}
In a seperate class of mine I wish to expose a following property.
public List<ITcpSerializable> RegisteredTypes { get; set; }
The problem is I am getting the following error.
Using the generic type
'ITcpSerializable' requires 1 type
arguments
Now I understand the error and how I could correct it but the problem is I do not wish to restrict my RegisteredTypes property to a specific typed implementation of my ITcpSerializable interface.
Is there a way around this problem? Hopefully what I am trying to accomplish is clear.
EDIT: OK i have completely stuffed up what I was trying to explain. Just clicked that my thinking was completely skewed. Please see this question for what I was actually asking: Constrain public property to specific types in List<Type>
You have to make a ITcpSerializable form of ITcpSerializable<T>. Then inherit from that with your generic version.
interface ITcpSerializable { }
interface ITcpSerializable<T> : ITcpSerializable { }
You can create a non-generic ITcpSerializable and inherit ITcpSerializable<T> from the new non-generic interface.
The Generic type argument definition in the interface is designed to require type safe results of a specific type when deserializing an object of a given type.
The particular use-case doesn't make sense to me, because you'd need to have an instance of an object in order to deserialize a different instance - which is not usually the way you'd want to go.
I understand you want to require that there's a strongly typed deserializer, but it would make sense to use some other pattern (like a Factory)
Furthermore, your input data is a byte[] - unless there is some other metadata, you have no way of knowing which implementor of ITCPSerializable needs to be called in order to get the correct concrete type.
The type information may be contained in the data (i.e. some header that includes type information) or by some other contract (i.e. always the same type).
The serialize method DOES make sense - because it's reasonable to ask an object for a serialized instance of itself, but the other way around is usually done by some other means.
So the solution to your problem would be to remove the generic type definition (which doesn't help you) and the Deserialize method (which doesn't make sense in this context), and just keep the Serialize method.
as in:
public interface ITcpSerializable
{
Byte[] Serialize();
}
And implement the Deserialize by using a factory.
You probably want to make your separate class generic also then, like:
public class MyClass<T> {
public List<ITcpSerializable<T>> RegisteredTypes { get; set; }
}
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.
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.