Convert ListDerivedClass to ListBaseClass
The way to make this work is to iterate over the list and cast the elements. This can be done using ConvertAll:
List<A> listOfA = new List<C>().ConvertAll(x => (A)x);
You could also use Linq:
List<A> listOfA = new List<C>().Cast<A>().ToList();
Convert List of Base Class to a List of Derived Class - possible?
Cast<T>
method applies cast operation to all elements of the input sequence. It works only if you can do the following to each element of the sequence without causing an exception:
ParentClass p = ...
ChildClass c = (ChildClass)p;
This will not work unless p
is assigned an instance of ChildClass
or one of its subclasses. It appears that in your case the data returned from the server API contains objects of ParentClass
or one of its subclasses other than ChildClass
.
You can fix this problem by constructing ChildClass
instances, assuming that you have enough information from the server:
List<ChildClass> childList = parentList
.Select(parent => new ChildClass(parent.Name, ... /* the remaining fields */))
.ToList();
Copying a ListBaseClass to ListDerivedClass
List<DerivedClass> result =
listBaseClass.ConvertAll(instance => (DerivedClass)instance);
Actually ConvertAll is good when you need to create new objects based on the original, when you just need to cast you can use the following
List<DerivedClass> result =
listBaseClass.Cast<DerivedClass>().ToList();
If not all of the items in your list can be cast to DerivedClass then use OfType instead
List<DerivedClass> result =
listBaseClass.OfType<DerivedClass>().ToList();
Cannot convert from ListDerivedClass to ListBaseClass
It is because List<T>
is in-variant
, not co-variant
, so you should change to IEnumerable<T>
which supports co-variant
, it should work:
IEnumerable<BaseClass> bcl = new List<DerivedClass>();
public void doSomething(IEnumerable<BaseClass> bc)
{
// do something with bc
}
Information about co-variant in generic
Casting List of Derived class to List of base class
The reason you cannot do this is because a list is writable. Suppose it were legal, and see what goes wrong:
List<Cat> cats = new List<Cat>();
List<Animal> animals = cats; // Trouble brewing...
animals.Add(new Dog()); // hey, we just added a dog to a list of cats...
cats[0].Speak(); // Woof!
Well dog my cats, that is badness.
The feature you want is called "generic covariance" and it is supported in C# 4 for interfaces that are known to be safe. IEnumerable<T>
does not have any way to write to the sequence, so it is safe.
class Animal
{
public virtual void Play(IEnumerable<Animal> animals) { }
}
class Cat : Animal
{
public override void Play(IEnumerable<Animal> animals) { }
}
class Program
{
static void Main()
{
Cat cat = new Cat();
cat.Play(new List<Cat>());
}
}
That will work in C# 4 because List<Cat>
is convertible to IEnumerable<Cat>
, which is convertible to IEnumerable<Animal>
. There is no way that Play can use IEnumerable<Animal>
to add a dog to something that is actually a list of cats.
C# convert Listbaseclass to ListDerivedClass
In your GetSensors
method, you are creating instances of the base class Sensor
. Trying to implicitly cast them to some other derived class is not possible. You should use a generic type parameter in that method and create instances of the actual derived type.
Like so: (notice the where
clause and the new
constraint of the T
parameter)
public static List<T> GetSensors<T>(JToken jToken) where T : Sensor, new()
{
var sensors = new List<T>();
try
{
foreach (var item in jToken)
{
var s = new T();
s.Label = item["lab"].ToString();
s.ActualTemp = item["tf"] != null ? item["tf"].ToString() : "";
s.HighTemp = item["hf"] != null ? item["hf"].ToString() : "";
s.LowTemp = item["lf"] != null ? item["lf"].ToString() : "";
sensors.Add(s);
}
}
catch (Exception)
{
}
return sensors;
}
Now call it like this:
List<IntSensor> iSensors = ParseJsonData.GetSensors<IntSensor>(internalSensorTree);
convert listbaseclass in Listderivedclass
Why do you inherit the Product
class? I think you want to add 2 more fields to the Product
class, right?
Because the auto-generated class is a partial
class, instead of inheriting the Product
class as you did, just add one more file to the partial class like this:
public partial class Product
{
public bool Restock { get; set; }
public DateTime? DateSold { get; set; }
}
C#, How to pass a List of a Derived class to a method that receives a List of the Base class?
The reason for such behaviour is explained here. In short - classes do not support variance in C# and List<AppleBox>
is not List<FruitBox<Apple>>
.
What you can do:
- "convert" collection (actually create a new one):
with OfType<>().ToList()
AppleBox.ChooseFirst(appleBoxes.OfType<FruitBox<Apple>>().ToList())
or just ToList
AppleBox.ChooseFirst(appleBoxes.ToList<FruitBox<Apple>>())
- change
ChooseFirst
signature to work with covariantIEnumerable<out T>
interface:
public abstract class FruitBox<T>
{
public T item;
public static T ChooseFirst(IEnumerable<FruitBox<T>> fruitBoxes)
{
return fruitBoxes.First().item;
}
}
C# Moq - Cannot convert ListDerivedClass to ListBaseClass
Because List<DerivedClass>
does not derive from List<BaseClass>
and the fact that the T
inside does is irrelevent when looking at it from that perspective.
What you're looking for is Covariance. There's MSDN documentation on it here: https://docs.microsoft.com/en-us/dotnet/standard/generics/covariance-and-contravariance
Most efficient way to cast ListSubClass to ListBaseClass
The syntax for this sort of assignment uses a wildcard:
List<SubClass> subs = ...;
List<? extends BaseClass> bases = subs;
It's important to realize that a List<SubClass>
is not interchangeable with a List<BaseClass>
. Code that retains a reference to the List<SubClass>
will expect every item in the list to be a SubClass
. If another part of code referred to the list as a List<BaseClass>
, the compiler will not complain when a BaseClass
or AnotherSubClass
is inserted. But this will cause a ClassCastException
for the first piece of code, which assumes that everything in the list is a SubClass
.
Generic collections do not behave the same as arrays in Java. Arrays are covariant; that is, it is allowed to do this:
SubClass[] subs = ...;
BaseClass[] bases = subs;
This is allowed, because the array "knows" the type of its elements. If someone attempts to store something that isn't an instance of SubClass
in the array (via the bases
reference), a runtime exception will be thrown.
Generic collections do not "know" their component type; this information is "erased" at compile time. Therefore, they can't raise a runtime exception when an invalid store occurs. Instead, a ClassCastException
will be raised at some far distant, hard-to-associate point in code when a value is read from the collection. If you heed compiler warnings about type safety, you will avoid these type errors at runtime.
Related Topics
Communicate Between Two Windows Forms in C#
Convert a String to an Enum in C#
C# Compiler Error: "Not All Code Paths Return a Value"
Use Unity API from Another Thread or Call a Function in the Main Thread
How to Execute a Stored Procedure Within C# Program
What's the @ in Front of a String in C#
What Are the Default Access Modifiers in C#
What Is the Yield Keyword Used For in C#
What's a "Static Method" in C#
How to Handle Both a Single Item and an Array For the Same Property Using Json.Net
How to Convert a Unix Timestamp to Datetime and Vice Versa
How Would I Run an Async Task≪T≫ Method Synchronously
Performance Differences Between Debug and Release Builds
How to Recursively List All the Files in a Directory in C#
In C#, Why Is String a Reference Type That Behaves Like a Value Type
How to Check If a Number Is a Power of 2
How to Escape Braces (Curly Brackets) in a Format String in .Net