object oriented Casting error [duplicate] - c#

This question already has answers here:
How to correctly cast a class to an abstract class when using type generics?
(4 answers)
Closed 4 years ago.
Casting Deriving Class as Base Class
I have a base abstract class which is generic and inherits from IComparable which is defined like below
public abstract class BaseClass<T> where T : IComparable
{
protected readonly T Data;
protected BaseClass(T data)
{
Data = data;
}
public abstract T Get();
}
Then I have defined a classe which inherits from this base class and has a specific generic type and is defined like below:
public class Name : BaseClass<String>
{
public Name(string data) : base(data)
{
}
public override string Get()
{
throw new NotImplementedException();
}
}
As generic type is string and string inherits from IComparable, I expect to be able to define new Name object with string value as generic type, but I get casting error for defining Name object like this:
BaseClass<IComparable> obj;
obj = new Name("behro0z");
and the error is
Error CS0029 Cannot implicitly convert type ConsoleApplication1.Name
to
ConsoleApplication1.BaseClass<System.IComparable> ConsoleApplication1

You're declaring a variable of type BaseClass<T>, and substitute T with IComparable.
That's valid, but that's not what your Name class is. That one derives from BaseClass<string>, not BaseClass<IComparable>, even though string implements IComparable.
You can either declare your variable obj to be of type BaseClass<string>, or the more derived type, Name.
Read up on covariance, C# Generics Inheritance Problem.

Related

C# how to assign a type to a generic type in AddScoped using interface? [duplicate]

This question already has answers here:
Pass An Instantiated System.Type as a Type Parameter for a Generic Class
(6 answers)
Closed 5 days ago.
I'm wanting to do a generic scoped.
I have a class where it needs to receive a "T" type to instantiate it. My problem is receiving this type "T" otherwise without being explicit.
example:
public class MyClass<T> : IMyInterface<T> where T : class {}
public interface IMyInterface<T> where T : class {}
public void test()
{
Type xx = new someClass1().GetType();
Type tt = new someClass2().GetType();
Type yy = new someClass3().GetType();
services.AddScoped<IMyInterface<xx>, MyClass<xx>>();
services.AddScoped<IMyInterface<tt>, MyClass<tt>>();
services.AddScoped<IMyInterface<yy>, MyClass<yy>>();
}
Another example
public void test()
{
foreach (Type item in someClass.ToList())
{
services.AddScoped<IMyInterface<item>, MyClass<item>>();
}
}
This allows the MyMethod method to create an instance of T using the new operator. Note that this approach requires that the type parameter T be constrained in some way in order to be used without being explicitly specified.
public void MyMethod<T>() where T : new()
{
T instance = new T();
// code
}

C#, can I declare a List<MyInterface<T>> of type Interface which has a generic type T? [duplicate]

This question already has answers here:
Generic list of generic objects
(3 answers)
Closed 3 years ago.
I want to do something, that I've done in Java.
I have an interface with a generic type like:
interface IDAO<T>
{
void Save(T data);
}
And I have two classes that implement this interface:
class BankAccountDAO : IDAO<BankAccount>
{
public void Save(BankAccount data){...}
}
class CategoryDAO : IDAO<Category>
{
public void Save(Category data) {...}
}
I need another class with a List which should be declare of type IDAO with generic type T so that I can add the concrete classes to this list like this:
class Manager
{
private List<IDAO> daoList = new List<IDAO>(); // here is the error
daoList.Add(new BankAccountDAO());
daoList.Add(new CategoryDAO());
public void myMethod(BankAccount b)
{
daoList.ElementAt(0).Save(b); // this should call the implemented Save() method of BankAccountDao
}
}
I did this in Java for a project but when I try to do this in C# I get an error:
CS0305 C# Using the generic type requires 1 type arguments
Is there any way I can do something like this?
You need to pass a type parameter to IDAO in your Manager class; in order to do that, you need some type that unifies with BankAccount and Category; if possible, I'd declare an interface called IBusinessObject which Category and BankAccount implement:
class Manager
{
private List<IDAO> daoList = new List<IDAO<IBusinessObject>>(); // add type parameter for IDAO
daoList.Add(new BankAccountDAO());
daoList.Add(new CategoryDAO());
public void myMethod(IBusinessObject b) // has to be IBusinessObject;
//you'll need to cast the underlying
///type to promote it to a BankAccount or Category.
{
daoList.ElementAt(0).Save(b); // this should call the implemented Save() method of BankAccountDao
}
}

Object oriented error [duplicate]

This question already has answers here:
How to correctly cast a class to an abstract class when using type generics?
(4 answers)
Closed 4 years ago.
What is the reason for this code error:
Casting Deriving Class as Base Class
public class Program
{
private static void Main(string[] args)
{
BaseClass<IComparable> baseClass;
baseClass = DateTime.Now.Ticks == 100 ? new Age(110) : new Name("behroz");
Console.WriteLine(baseClass.Get());
Console.ReadKey();
}
}
public abstract class BaseClass<T> where T : IComparable
{
protected readonly T Data;
protected BaseClass(T data) => Data = data;
public abstract T Get();
}
public class Name : BaseClass<String>
{
public Name(string data) : base(data) { }
public override string Get() => "Name :" + Data;
}
public class Age : BaseClass<Int64>
{
public Age(Int64 data) : base(data) { }
public override Int64 Get() => 10 + Data;
}
You should listen to the compiler. You should be getting this error:
The type 'System.IComparable' cannot be used as type parameter 'T' in the generic type or method 'BaseClass'. There is no implicit reference conversion from 'System.IComparable' to 'System.IComparable'.
That's you're first issue.
So you could change the BaseClass<T> to be this: public abstract class BaseClass<T> where T : IComparable.
Bu now you have this error:
Type of conditional expression cannot be determined because there is no implicit conversion between 'Age' and 'Name'
That's because your DateTime.Now.Ticks == 100 ? new Age(110) : new Name("behroz") isn't making sure you're specifying a common type.
Now if I try to change it to DateTime.Now.Ticks == 100 ? (BaseClass<IComparable>)new Age(110) : (BaseClass<IComparable>)new Name("behroz") then I get these errors:
Cannot convert type 'Age' to 'BaseClass'
Cannot convert type 'Name' to 'BaseClass'
Now this is where it gets more interesting.
Just because Int64 is an IComparable it does not mean that BaseClass<Int64> is a BaseClass<IComparable>. It's not.
Same with BaseClass<String> and BaseClass<IComparable>.
You simply can't use BaseClass<IComparable> for the types Name and Age.
You are trying to initiate abstract class, which is wrong.
BaseClass baseClass;
baseClass = new Age(110);
Casting deriving class(i.e. BaseClass) as base class is causing this issue.
You can directly call the class based on your conditions.

Error assigning class implementing generic interface to generic variable [duplicate]

This question already has answers here:
Generics and casting - cannot cast inherited class to base class
(3 answers)
Closed 5 years ago.
With reference to InvalidCastException on Generics, I have adapted the given answer for my own application. As an example:
public interface IData
{
string getValue();
}
public interface IController<in T> where T : IData
{
string formString(T data);
}
public class DataImplA : IData
{
public string getValue()
{
return "DataImplA";
}
}
public class ControllerImplA : IController<DataImplA>
{
public string formString(DataImplA data)
{
return "ControllerImplA, " + data.getvalue();
}
}
public class Program
{
private static IController<IData> controller;
public static void main(string[] args)
{
// Line with error
Program.controller = (IController<IData>)new ControllerImplA();
Console.WriteLine(Program.controller.formString(new DataImplA()));
}
}
During runtime, the indicated line will trigger
InvalidCastException: Unable to cast object of type 'ControllerImplA' to type 'IController`1[IData].
I tried changing to Program.controller = (IController<IData>)new ControllerImplA<DataImplA>(); but this results in the compilation error The non-generic type 'ControllerImplA' cannot be used with type arguments
I then tried changing the class definition to public class ControllerImplA<DataImplA> : IController<DataImplA> but then the new compilation error is:
The type 'DataImplA' cannot be used as type parameter 'T' in the generic type or method 'IController T'. There is no boxing conversion or type parameter conversion from 'DataImplA' to 'IData'.
I don't want to use public class ControllerImplA<T> : IController<T> because the constraint is that ControllerImplA can only use DataImplA, ControllerImplB can only use DataImplB and so on so forth.
How should I correct my original code?
In my opinion, Generic class is actually a placeholder for classes. By type "T", it creates different types/classes in runtime. Which means IController<IData> and IController<DataImplA> are totally different classes, they have no inheritance relationship.

Base Class Generic Arguments Clarification [duplicate]

This question already has answers here:
What does new() mean?
(3 answers)
Closed 6 years ago.
I have an Abstract class that is implemented like this:
public abstract class BaseImplementation<T, U> : IHistory<T>
where T : class, IEntity, new()
where U : DbContext, new()
I understand that the generic argument <U> is an EF DbContext.
I understand that the generic argument <T> must be a class that implements the IEntity Interface.
What is the "new()"? Must be a new instance of a given class? What is the purpose of that?
Note that is declared in both <T> and <U>
Thank you.
From the docs:
"The new constraint specifies that any type argument in a generic class declaration must have a public parameterless constructor. To use the new constraint, the type cannot be abstract."
I don't really have much more to add to this as I think the explanation above is sufficient.
The new() is called a new constraint and it requires that the type argument has a public, parameterless constructor.
The benefit of using it is that you can create an instance of your generic type inside the class, without explicitly knowing the type passed in.
For example:
public PersonEntity : IEntity
{
// public parameterless constructor
public PersonEntity()
{
}
}
public abstract class BaseImplementation<T, U> : IHistory<T>
where T : class, IEntity, new()
where U : DbContext, new()
{
public T CreateEntity()
{
var entity = new T();
// entity will be the type passed to `T` when instantiating `BaseImplementation`
}
}
Then usage would be something like:
public class PersonImpl : BaseImplementation<PersonEntity, DataContext>
{
public void Method1()
{
var entity = CreateEntity();
// entity is typeof(PersonEntity);
}
}
new() is a constraint specifying that the type argument must have a public parameterless constructor. For more information about the generic type constraint, see MSDN。

Categories

Resources