I'm trying to understand the exact difference between the 3 following methods of the ImmutableArray struct:
- the static method ImmutableArray<T>.CastUp<TDerived>
- the instance method ImmutableArray<T>.As<TOther>
- the instance method ImmutableArray<T>.CastArray<TOther>
I found myself studying these methods because I have the need to convert an existing instance of ImmutableArray<TDerived>
to an instance of ImmutableArray<TBase>
.
My scenario is similar to the following:
public interface IFoo {}
public sealed class Foo: IFoo {}
ImmutableArray<Foo> fooClassArray = GetFoos();
ImmutableArray<IFoo> fooInterfaceArray = // convert from fooClassArray instance
Based on my understanding, the way to do so efficiently is by using the ImmutableArray<T>.CastUp<TDerived> static method. So, I could solve my problem this way:
ImmutableArray<IFoo> fooInterfaceArray = ImmutableArray<IFoo>.CastUp(fooClassArray);
If I get it correctly, by doing so there is no need to reallocate the underlying array: the array being wrapped by fooClassArray
is reused and there is no need to allocate a brand new array for fooInterfaceArray
.
First question: is my understanding about ImmutableArray<T>.CastUp<TDerived> correct ?
By looking through the documentation for the ImmutableArray<T> struct I spotted the ImmutableArray<T>.As<TOther> method and the ImmutableArray<T>.CastArray<TOther> method.
What is the difference between them ?
What is the intended usage of them ? It seems to me that they both solve the same use case.
Are they used to perform downcasts operations (as opposed to ImmutableArray<T>.CastUp<TDerived>, which is actually used to perform upcast operations) ?
CodePudding user response:
Your understanding about ImmutableArray<T>.CastUp<TDerived>
method is good. This method that returns a new ImmutableArray<TDerived>
that is a copy of the original ImmutableArray<T>
with the elements cast to TDerived using the as operator.
In summary, CastUp<TDerived>
is used when you want to convert an ImmutableArray<T>
to an ImmutableArray<TDerived>
where T is a base class or interface and TDerived is a derived class, and you want to handle the case where an element of the original array cannot be explicitly converted to TDerived by setting it to null in the resulting array.
Regarding the methods ImmutableArray<T>.As<TOther>
and ImmutableArray<T>.CastArray<TOther>
, As<TOther>
is used when you want to convert an ImmutableArray<T>
to an ImmutableArray<TOther>
and you are certain that all elements of the original array can be explicitly converted to TOther.
Here is an example of using As<TOther>
:
ImmutableArray<int> array = ImmutableArray.Create(1, 2, 3);
ImmutableArray<double> doubleArray = array.As<double>();
Console.WriteLine(doubleArray[0]); // Output: 1
CastArray<TOther>
is used when you want to convert an ImmutableArray<T>
to an ImmutableArray<TOther>
and you are not certain that all elements of the original array can be explicitly converted to TOther, and you want to handle the case where an element cannot be converted by setting it to null in the resulting array.
Here is an example of using CastArray<TOther>
:
ImmutableArray<object> array = ImmutableArray.Create(1, "2");
ImmutableArray<int> intArray = array.CastArray<int>();
console.WriteLine(intArray[0]); // Output: 1
console.WriteLine(intArray[1]); // Output: null
CodePudding user response:
CastUp
doesn't copy the array, as you said. It is very efficient to use, as long as each element is trivially castable to a base type. Note that boxing or converting don't count as trivially casting (ie trying to use that to change int
to long
will fail):
public static ImmutableArray<T> CastUp<TDerived>(ImmutableArray<TDerived> items)
where TDerived : class?, T
{
return new ImmutableArray<T>(items.array);
}
CastArray
seems to simply cast the entire array to the type you ask. It can work with covariance, so it should be more or less equivalent to the first function (again, boxing doesn't count). Be careful of the parameter type however, it is not an ImmutableArray
:
public ImmutableArray<TOther> CastArray<TOther>() where TOther : class?
{
return new ImmutableArray<TOther>((TOther[])(object)array!);
}
As
is the generalization of CastUp
, allowing you to also cast down, at a cost:
public ImmutableArray<TOther> As<TOther>() where TOther : class?
{
return new ImmutableArray<TOther>((this.array as TOther[]));
}