Using generics with IEnumerable in base class constructor - c#

Why does this code gives this error?
Argument type 'System.Collections.Generic.IEnumerable<T>' is not
assignable to parameter type
'System.Collections.Generic.IEnumerable<[...].IExample>'
public interface IExample { }
public class BaseClass
{
public BaseClass(IEnumerable<IExample> a) { }
}
public class FailingClass<T> : BaseClass
where T : IExample
{
public FailingClass(IEnumerable<T> a): base(a) { } //error here on base(a)
}

You are missing the class constraint to T within FailingClass.
IEnumerable<T> has a type parameter marked as covariant. Covariance enables you to use a more derived type than originally specified. Variance in general applies to reference types only.
So what the class constraint actually does here is enforcing a constraint to pass a reference type. If you were to pass in a value type for T, that type parameter is invariant for the resulting constructed type and does not suffice IEnumerable<T>.
using System.Collections.Generic;
public interface IExample { }
public class BaseClass
{
public BaseClass(IEnumerable<IExample> a) { }
}
public class FailingClass<T> : BaseClass
where T : class, IExample
{
public FailingClass(IEnumerable<T> a): base(a) { } //error here on base(a)
}

Related

There is no implicit reference conversion from generic type to 'System.Data.Objects.DataClasses.EntityObject'

I'm have created a base class with has the starting code:
public abstract class BaseServices<TObject> : IDisposable
where TObject : EntityObject
{
public TObject Get(int id)
{
return _context.Set<TObject>().Find(id);
}
}
on the other hand my derived class contains:
public class AmountDLL : BaseServices<Tbl_Amount>
//:Base<Tbl_Amount>
{
public override ICollection<Tbl_Amount> GetAll()
{
return base.GetAll();
}
}
when i run the code it gives error that is:
The type 'Tbl_Amount' cannot be used as type parameter 'TObject' in the generic type or method 'BaseServices'. There is no implicit reference conversion from 'Tbl_Amount' to 'System.Data.Objects.DataClasses.EntityObject'
Please suggest me what is wrong with my code
Thanks
The Tbl_Amount-class has to look like:
using System.Data.Objects.DataClasses;
public class Tbl_Amount : EntityObject
{
//Class code
}

C# generic Interface implementation to derived class

I am stuck in implementation of generic class and interface. I am not sure what i wanted to do is possible or not.
here is my code:-
I have defined a generic class whose type not define like
public class Response<T>
{
public T Data { get; set; }
public Response()
{
Data = default(T);
}
}
and a Interface which right now have one function
public interface IOInterface<T> where T : Response<T>
{
Response<T> ReadAdvantechChannel(Dictionary<string, string> IOParameters);
}
And one derive class who will implements this interface :-
public class AdvantechOperation : IOInterface<T>
{
public Response<AIRecordInfo> ReadAdvantechChannel(Dictionary<string, string> IOParameters)
{
Response<AIRecordInfo> resp = new Response<AIRecordInfo>();
}
}
and AIrecordinfo is again class
public class AIRecordInfo
{
double[] ArryMaxValueAIdouble;
double[] ArryMinValueAIdouble;
double[] ArryAVGValueAIdouble;
}
what i want to do that implement a class who implement define interface but return type of interface function is not clear for my future derived class thats why i have made it generic and try to implement it my present class "AdvantechOperation". My interface will have three functions and all function return type will different to each other thats why i made it generic return type Response and in my present class AdvantechOperation, T replaced by AIRecordInfo.
But I am facing below Error while compiling this project
Error 7 The type 'T' cannot be used as type parameter 'T' in the
generic type or method 'IOModule.IOInterface'. There is no boxing
conversion or type parameter conversion from 'T' to
'IOModule.Response'. D:\MTS\SMS\DAQAdvantechdll\DAQAdvantechdll\IOCommunication.cs 28 18 IOModule
Error 8 'IOModule.AdvantechOperation' does not implement interface
member
'IOModule.IOInterface.ReadAdvantechChannel(System.Collections.Generic.Dictionary)'.
'IOModule.AdvantechOperation.ReadAdvantechChannel(System.Collections.Generic.Dictionary)'
cannot implement
'IOModule.IOInterface.ReadAdvantechChannel(System.Collections.Generic.Dictionary)'
because it does not have the matching return type of
'IOModule.Response'. D:\MTS\SMS\DAQAdvantechdll\DAQAdvantechdll\IOCommunication.cs 28 18 IOModule
Get rid of the generic type constraint for your interface and use AIRecordInfo as the generic type argument when implementing the interface:
public class AdvantechOperation : IOInterface<AIRecordInfo>
{ ... }
It seems to me that you want this:
public class Response<T> { }
public interface IOInterface<T> where T : Response<T>
{
T ReadAdvantechChannel(Dictionary<string, string> IOParameters);
}
public class AdvantechOperation : IOInterface<AIRecordInfo>
{
public AIRecordInfo ReadAdvantechChannel(Dictionary<string, string> IOParameters)
{
return new AIRecordInfo();
}
}
public class AIRecordInfo : Response<AIRecordInfo>
{
double[] ArryMaxValueAIdouble;
double[] ArryMinValueAIdouble;
double[] ArryAVGValueAIdouble;
}
Response<T> no longer needs a body because IOInterface<T>'s method simply returns T which must inherit from Response<T>.

Generic Constraints C#

I need to make some of my classes inherit from Interface with generic field
like that
public Interface ICommon<Ttype>
{
Ttype Filed{get;set;}
}
public Class class1:Icommon<int>
{
int Filed{get;set;}
}
public Class class2:Icommon<double>
{
double Filed{get;set;}
}
I created a generic class with constraints that uses classes class1 and class2 to make some operations like that:
public Class GenericClass<Ttype,Tcommon> where Ttype:ICommon<Tcommon>
{
//forexample
public Ttype someOperation(Ttype x)
{
var a=x.Field;
//.............
}
}
every time I use the GenericClass I have to know the type of Field of the class I used say class1 or class2 to be able to pass it to match the generic constraint
Is there a way to write GenericClass like that:
public Class GenericClass<Ttype,Tcommon> where Ttype:**ICommon**
{
//forexample
public Ttype someOperation(Ttype x)
{
var a=x.Field;
//.............
}
}
by writting ICommon without <TCommon> ??
Update:
or how to edit ICommon interface to be like that
public Interface ICommon
{
Ttype Filed{get;set;}
}
I hope I understood what you intended to do:
public interface ICommon<T>
{
T Field { get; set; }
}
public class GenericClass<T>
{
public ICommon<T> SomeOperation(ICommon<T> x)
{
// do your stuff
}
}
Short answer is: no.
You need to tell the compiler type of generic argument.
In fact, GenericClass<int> and GenericClass<string> are two different classes in CLR.

C# The is no implicit reference conversion from 'B' to 'A' using Generics

I'm with problems to convert from the type derived to base type using Generics.
Class to manage the dictionary:
public class ManagerDictionary<TContext>
{
public ManagerDictionary()
{
this.Dictionary = new Dictionary<int, TContext>();
}
public IDictionary<int, TContext> Dictionary { get; private set; }
public void Register<TSubContext>(int context, TSubContext subContext) where TSubContext : TContext
{
this.Dictionary[context] = subContext;
}
}
Interface of the Process context:
public interface IProcessContext : IContext<ProcessViewModel>
{
}
My test class:
public class Foo<TViewModelContext> where TViewModelContext : ViewModeBase
{
public Foo(IProcessContext processContext)
{
// Create de Dictionary Manager.
this.ManagerDictionary = new ManagerDictionary<IContext<TViewModelContext>>();
// Register the process context on dictionary.
// The error is occurring here: The is no implicit reference conversion from 'IProcessContext' to 'IContext<TViewModelContext>'
this.ManagerDictionary.Register((int)ContextType.Process, processContext);
}
protected ManagerDictionary<IContext<TViewModelContext>> ManagerDictionary { get; set; }
}
When I try register the processContext, the problem occurs:
The is no implicit reference conversion from 'IProcessContext' to
IContext<TViewModelContext>
How can I resolve this problem?
Edit:
When I Create a inherited class of the Foo, I can register, but I need register on Foo class too.
public interface IAnotherProcessContext : IContext<ProcessTwoViewModel>
{
}
public class InheritedFoo : Foo<ProcessTwoViewModel>
{
public InheritedFoo(IAnotherProcessContext anotherProcessContext)
{
base.ManagerDictionary.Register((int)ContextType.InheritedProcess, anotherProcessContext);
}
}
You're trying to treat IContext<T> as if it's covariant with respect to T, but that interface isn't defined as being covariant.
Either make the interface be covariant, or alter your program such that you never expect an IContext<Child> to be implicitly convertible to an IContext<Parent>.

Calling methods and properties of reference types in generic classes

While there are plenty of example on generics using primitve types like int ans string I couldn't really find one using proper classes. Here is the scenario
//main program
class Program
{
static void Main(string[] args)
{
MyClass<TClass> mt = new MyClass<TClass>();
mt.GetValueFromType();
Console.ReadKey();
}
}
This is the generic class
public class MyClass<T>
{
public void GetValueFromType()
{
Console.WriteLine("Genric method called");
//Need to call the method MyTypeMethod() from the reference type sent in here.
//How?
}
}
One of the types that will be sent in to the generic class as
public class TClass
{
public void MyTypeMethod()
{
Console.WriteLine("Type method called");
}
}
Can this even be done in C# or do I need to refer to an interface of TClass with the new MyClass<T>().GetValueFromType() method ?
If I have to use interface then why use generics at all?
All the compiler can infer is that generic parameter T is of type Object so only the methods and properties for System.Object will be available. In order to get beyond that, you need to tell the compiler that T is expected to be derived from a base type, or implements specific interfaces. This is called a generic constraint:
public abstract class BaseClass
{
public virtual void MyTypeMethod()
{
}
}
public class TClass : BaseClass
{
public override void MyTypeMethod()
{
Console.WriteLine("Type method called");
}
}
public class MyClass<T> where T: BaseClass
{
public void GetValueFromType(T value)
{
Console.WriteLine("Genric method called");
value.MyTypeMethod();
}
}
So in this example any class derived from BaseClass can be used for the generic parameter T. You can also do the same thing with an interface. But in that case it would be more along the lines of that T implements the constrained interface. Usually the interface route is much more flexible since c# does not allow multiple inheritance.
You can use generic constrains what I think will accomplish what your after:
public class MyClass<T> where T: TClass
{
public void GetValueFromType(T value)
{
Console.WriteLine("Genric method called");
value.MyTypeMethod();
}
}
I'd create an abstract base class, say MyBase that defines the method MyTypeMethod():
public abstract class MyBase
{
public virtual void MyTypeMethod() { }
}
All the classes you want to use in the generic class would inherit from this. Override and implement MyTypeMethod()
Modify your generic class:
public class MyClass<T> where T : MyBase
{
public void GetValueFromType()
{
T.MyTypeMethod();
Console.WriteLine("Generic method called");
}
}
You could also use an interface as gleng suggested.

Categories