Custom generic list of generic class - c#-4.0

I got a class
public class ID_Name<T>
{
public ID_Name(T id)
{
this.ID = id;
}
public T ID { get; set; }
public string Name
{
get
{
return Helper.SomeReturnValue;
}
}
}
All I want to do is generate a custom List of ID_Name where I can pass an ID_Name.ID as parameter in Add.
I tried the following:
public class ID_Name_List<T> : IList<T> where T : ID_Name<T>
but then I get the following error:
The type "EProtokollStatus" cannot be used as type parameter "T" in
the generic type or method "ID_Name_List<\T>". There is no boxing
conversion or type parameter conversion from "EProtokollStatus" in
ID_Name<\EProtokollStatus>.
I read something about this issue here: No boxing or type parameter conversion for generic Type parameter but I can't see a restriction except ID_Name here.
This may be wrong somehow, because everything I want to express is "use the same type T as in ID_Name for ID_Name_List", but how do I achieve that?
I found something here: C#: Declaring and using a list of generic classes with different types, how? but I don't want to create many different classes for all possible types.
All I want to achieve is something like
ID_Name_List<EProtokollStatus> myList = new ID_Name_List<EProtokollStatus>();
myList.Add(EProtokollStatus.ValueX);

Your current constraint makes no sense. Did you mean:
public class ID_Name_List<T> : IList<ID_Name<T>>

Related

How to create a Generic list parameter which will accept all the type of classes?

public void GenerateExcelReport(List<EventHistory> lstData)
{
}
I am using the above list as Parameter (i.e. the list of type "EventHistory" class) if I want to pass all types of lists, then how to create the list parameter generally?
If you want to process all kind of lists, the only thing that is generic is the t in the List<T>:
public void GenerateExcelReport<T>(List<T> lstData)
{
// ...
}
Documentation: Generic Methods
Since you've mentioned that you want to "accept all the type of classes?", you could add a constraint to allow only classes and not value types:
public void GenerateExcelReport<T>(List<T> lstData) where T: class
{}
You need to add the generic type parameter for T to your method:
void GenerateExcelReport<T>(List<T> list){
}
Then call it:
GenerateExcelReport(stringList);
GenerateExcelReport(objectList);

Overriding parent methods with contravariant arguments

Basically, I want to override a parent class with different arguments. For example:
class Hold<T> {
public var value:T;
public function new(value:T) {
set(value);
}
public function set(value:T) {
this.value = value;
}
}
Then override that class, something like:
class HoldMore extends Hold<T> {
public var value2:T;
public function new(value:T, value2:T) {
super(value);
set(value, value2);
}
override public function set(value:T, value2:T) {
this.value = value;
this.value2 = value2;
}
}
Obviously this will return an error, Field set overloads parent class with different or incomplete type. Is there a way around this? I tried using a public dynamic function, and then setting set in the new() function, but that gave a very similar error. Any thoughts?
This is just a complement to #stroncium's answer, which is totally correct.
Here is an example how it could look like:
class Hold<T> {
public var value:T;
public function new(value:T) {
set(value);
}
public function set(value:T) {
this.value = value;
}
}
class HoldMore<T> extends Hold<T> {
public var value2:T;
public function new(value:T, value2:T) {
super(value);
setBoth(value, value2);
}
// you cannot override "set" with a different signature
public function setBoth(value:T, value2:T) {
this.value = value;
this.value2 = value2;
}
}
alternatively, you could use an array as parameter or a dynamic object holding multiple values in order to "set" them using the same method, but you loose some of the compiler's type checking.
If you wrote the base class you could add an optional argument to it, this would be a workaround though, not directly what you want to do.
In the current state it totally won't work. There is not only 1 problem, but few of them:
Type T is meaningless in context of this new class, you should either use some concrete type or template this class over T.
You can not change the number of arguments of function when overriding it. However you can add another function(with a different name) to accept 2 arguments and do what you want (which is the way you would use in most languages, by the way).
I don't really understand how you see a contravariance problem there. The actual problem is that haxe doesn't support function overload. (It actually does, the function signature is name + full type, but that's not what you would want to write nor support, and is mostly used for js/java externs.)
Unfortunately the language doesn't allow it.

Type parameters - get concrete type from type T : IMyInterface

Suppose I have a List<IMyInterface>...
I have three classes which implement IMyInterface: MyClass1, MyClass2, and MyClass3
I have a readonly Dictionary:
private static readonly Dictionary<Type, Type> DeclarationTypes = new Dictionary<Type, Type>
{
{ typeof(MyClass1), typeof(FunnyClass1) },
{ typeof(MyClass2), typeof(FunnyClass2) },
{ typeof(MyClass3), typeof(FunnyClass3) },
};
I have another interface, IFunnyInteface<T> where T : IMyInterface
I have a method:
public static IFunnyInterface<T> ConvertToFunnyClass<T>(this T node) where T : IMyInterface
{
if (DeclarationTypes.ContainsKey(node.GetType())) {
IFunnyInterface<T> otherClassInstance = (FunnyInterface<T>) Activator.CreateInstance(DeclarationTypes[node.GetType()], node);
return otherClassInstance;
}
return null;
}
I'm trying to call the constructor of FunnyClasses and insert as parameter my MyClass object. I don't want to know which object it is: I just want to instantiate some FunnyClass with MyClass as a parameter.
What happens when I call ConvertToFunnyClass, T is of type IMyInterface, and when I try to cast it to FunnyInterface<T>, it says I can't convert FunnyClass1, for instance, to FunnyInterface<IMyInterface>
My current workaround (not a beautiful one), is this:
public static dynamic ConvertToFunnyClass<T>(this T node) where T : IMyInterface
{
if (DeclarationTypes.ContainsKey(node.GetType())) {
var otherClassInstance = (FunnyInterface<T>) Activator.CreateInstance(DeclarationTypes[node.GetType()], node);
return otherClassInstance;
}
return null;
}
And I don't like it because the return type is dynamic, so when I access it from somewhere else, I have no idea what type it is, and I lose intellisense, and stuff. I don't know about any performance implications either.
Any clues?
Thanks in Advance!
Resolution
As I'm using C# 4.0, I could stop casting errors using covariance (output positions only), and so I changed my IFunnyInterface to
IFunnyInteface<out T> where T : IMyInterface
Thank you all for the replies.
Essentially, your problem is that you are trying to convert FunnyInterface<T> to FunnyInterface<IMyInterface>. As has been mentioned several times (one example is here, more information here), this is not valid in most circumstances. Only in .NET 4, when the generic type is an interface or delegate, and the type parameter has been explicitly declared as variant with in or out, can you perform this conversion.
Is FunnyInterface actually an interface?
thecoop answer points you exactly to why you can't do it.
A cleaner solution to the problem (besides using dynamic) would be a base non-Generics Interface:
public interface IFunnyInterfaceBase
{
}
public interface IFunnyInteface<T> : IFunnyInterfaceBase
where T : IMyInterface
{
}
And you need to move methods signature you use in that code from IFunnyInteface to IFunnyInterfaceBase.
This way you would be able to write something like this:
MyClass2 c2 = new MyClass2();
IFunnyInterfaceBase funnyInstance = c2.ConvertToFunnyClass();
The Exception you said you got in your code is not due to the extension method signature itself (the method is fine)..it is originated by the type of your lvalue (the type of the variable you use to store its return value)!
Obviously this solution applies only if you can modify IFunnyInterface source code!

EF generic method overloading

I'd like make possible a generic method overload.
Since I need to create an ObjectSet<..> without knowing the generic type contained in, I wold build something like this:
public IQueryable<T> MyMethod<T>() where T : class, (IMyFirst || IMySecond) //notice the syntax..!
{
if(typeOf(T) is IMyFirst..
else ...
}
How can I reach my purpose..?
Update:
#BrokenGlass wrote:
This type of constraint is not possible in C# - you could however constrain to IFoo and have IMyFirst and IMySecond both implement IFoo.
But that suggestion is not applicable, please see this:
interface1 { property1 {..}}
interface2 { property2 {..}}
interfaceIFoo : interface1, interface2 { }
by any method:
MyWrapper.Retrieve<EntityProduct>(myObjContext); //error-> EntityProduct implements interface1 only!!
by other any method:
MyWrapper.Retrieve<EntityOrder>(myObjContext); //error-> EntityOrder implements interface2 only!!
and here:
public static IQueryable<T> Retrieve<T>(ObjectContext context) where T :class, interfaceIFoo
{
var query = context.CreateObjectSet<T>().AsQueryable();
//...
This type of constraint is not possible in C# - you could however constrain to IFoo and have IMyFirst and IMySecond both implement IFoo.
If you can live with dependencies on Entity Framework you could alternatively also use EntityObject
A disjunctive generic constraint doesn't really make sense. Those constraints provide compile-time information to the method, so there's not much point in constraints that result in an ambiguous type at compile time. For instance, if your method is just going to resort to run-time type checking, you might as well just do this:
public IQueryable<T> MyMethod<T>() where T : class
{
if (typeOf(T) is IMyFirst) ...
else ...
}
If you feel you need the type checking on input and a pseudo-abstraction, perhaps extension methods that happen to be identically named would suffice:
public static IQueryable<IMyFirst> MyMethod(this IMyFirst input)
{
return ...
}
public static IQueryable<IMySecond> MyMethod(this IMySecond input)
{
return ...
}

Problem using Lazy<T> from within a generic abstract class

I have a generic class that all my DAO classes derive from, which is defined below. I also have a base class for all my entities, but that is not generic.
The method GetIdOrSave is going to be a different type than how I defined SabaAbstractDAO, as I am trying to get the primary key to fulfill the foreign key relationships, so this function goes out to either get the primary key or save the entity and then get the primary key.
The last code snippet has a solution on how it will work if I get rid of the generic part, so I think this can be solved by using variance, but I can't figure out how to write an interface that will compile.
public abstract class SabaAbstractDAO<T> :ISabaDAO<T> where T:BaseModel
{
...
public K GetIdOrSave<K>(K item, Lazy<ISabaDAO<BaseModel>> lazyitemdao)
where K : BaseModel
{
...
}
I am getting this error, when I try to compile:
Argument 2: cannot convert from 'System.Lazy<ORNL.HRD.LMS.Dao.SabaCourseDAO>' to 'System.Lazy<ORNL.HRD.LMS.Dao.SabaAbstractDAO<ORNL.HRD.LMS.Models.BaseModel>>'
I am trying to call it this way:
GetIdOrSave(input.OfferingTemplate,
new Lazy<ISabaDAO<BaseModel>>(
() =>
{
return (ISabaDAO<BaseModel>)new SabaCourseDAO() { Dao = Dao };
})
);
If I change the definition to this, it works.
public K GetIdOrSave<K>(K item, Lazy<SabaCourseDAO> lazyitemdao) where K : BaseModel
{
So, how can I get this to compile using variance (if needed) and generics, so I can have a very general method that will only work with BaseModel and AbstractDAO<BaseModel>? I expect I should only need to make the change in the method and perhaps abstract class definition, the usage should be fine.
UPDATE:
With a very helpful response I have a slightly improved example, but an interesting dilemna:
I have this defined now, and I don't have any in or out on T here because I get errors that contradict, if out T then I get that it must be contravariantly valid and if in T then covariantly valid, so I made it invariant, since it appears VS2010 can't figure it out.
public interface ISabaDAO<T> where T:BaseModel
{
string retrieveID(T input);
T SaveData(T input);
}
I get this error, though it did compile:
System.InvalidCastException: Unable to cast object of type 'ORNL.HRD.LMS.Dao.SabaCourseDAO' to type 'ORNL.HRD.LMS.Dao.ISabaDAO`1[ORNL.HRD.LMS.Models.BaseModel]'.
I fixed two code snippets above, but it appears that variance won't work as I hoped here.
I had tried this:
public delegate K GetIdOrSave<out K>(K item, Lazy<ISabaDAO<BaseModel>> lazyitemdao)
where K : BaseModel;
but I get the same problem as with the interface, if I put out it complains, so I put in and the opposite complaint.
I think I could get this to work if this was legal:
public delegate K GetIdOrSave<K>(in K item, out Lazy<ISabaDAO<BaseModel>> lazyitemdao)
where K : BaseModel;
C# 4.0 support for covariance and contravariance when working with delegates and interfaces.
How is Generic Covariance & Contra-variance Implemented in C# 4.0?
So if you can use the generic delegate Lazy with a Interface as parameter so try somthing like this:
//covariance then you can save Giraffe as SicilianGiraffe but you cannot save Giraffe as Animal; contr-variance realization is not imposible in your case(just theoreticaly)
public interface ISabaDAO<out T> where T: BaseModel{
int retrieveID(BaseModel);
T SaveData(BaseModel);
}
public abstract class SabaAbstractDAO<T> : ISabaDAO<T>{
...
// in this case Lazy should be covariance delegate too
// delegate T Lazy<out T>();
public K GetIdOrSave<K>(K item, Lazy<ISabaDAO<BaseModel>> lazyitemdao) where K : BaseModel
{
...
return (K)itemdao.SaveData(item);// is not safe
...
}
}
public class Course : BaseModel{}
public class SabaCourseDAO : SabaAbstractDAO<Course>{}
//so you can cast SabaCourseDAO to ISabaDAO<Course> and ISabaDAO<Course> to ISabaDAO<BaseModel>
// then next invoking should be valid
GetIdOrSave(new Course (), new Lazy<ISabaDAO<Course>>(() =>
{
return new SabaCourseDAO() { Dao = Dao };
})
Cannot check it. I have not got VS2010.

Resources