C# Cast Entire Array?
Asked Answered
S

5

83

I see this Array.ConvertAll method, but it requires a Converter as an argument. I don't see why I need a converter, when I've already defined an implicit one in my class:

    public static implicit operator Vec2(PointF p)
    {
        return new Vec2(p.X, p.Y);
    }

I'm trying to cast an array of PointFs to an array of Vec2s. Is there a nice way to do this? Or should I just suck it up and write (another) converter or loop over the elements?

Shaeffer answered 14/1, 2010 at 22:47 Comment(2)
@Terry: I ask a lot of trivial questions because I'm always surprised by the answers :) It's easy to solve a problem, but hard to do it elegantly.Shaeffer
Duplicate: #944674Allgood
K
130

The proposed LINQ solution using Cast/'Select' is fine, but since you know you are working with an array here, using ConvertAll is rather more efficienct, and just as simple.

var newArray = Array.ConvertAll(array, item => (NewType)item);

Using ConvertAll means
a) the array is only iterated over once,
b) the operation is more optimised for arrays (does not use IEnumerator<T>).

Don't let the Converter<TInput, TOutput> type confuse you - it is just a simple delegate, and thus you can pass a lambda expression for it, as shown above.

Kappenne answered 14/1, 2010 at 22:57 Comment(3)
Works perfectly! Thank you! I thought I had to define the <types>.Shaeffer
No problem. And yeah, in C# 2.0 and before you would have had to define a type - fortunately those days are gone.Kappenne
um, actually, I believe none of the proposed solutions will make the array be iterated twice, since both Cast and Select are implemented using deferred execution: msdn.microsoft.com/en-us/library/… msdn.microsoft.com/en-us/library/…Orebro
P
43

As an update to this old question, you can now do:

myArray.Cast<Vec2>().ToArray();

where myArray contains the source objects, and Vec2 is the type you want to cast to.

Pinon answered 30/10, 2013 at 17:23 Comment(1)
Namespace required: using System.LinqBelva
S
23

Cast doesn't consider user defined implicit conversions so you can't cast the array like that. You can use select instead:

myArray.Select(p => (Vec2)p).ToArray();

Or write a converter:

Array.ConvertAll(points, (p => (Vec2)p));

The latter is probably more efficient as the size of the result is known in advance.

Scope answered 14/1, 2010 at 22:55 Comment(0)
F
5

The most efficient way is:

class A { };
class B : A { };

A[] a = new A[9];
B[] b = a as B[];
Frankfort answered 27/12, 2019 at 11:38 Comment(1)
This is fast but b will always be null. You can't cast from an A[] to a B[] because the A array may contain non-B instances (e.g. C : A); that is, not every A is necessarily also a B. Instead, if you did B[] b = new B[9]; A[] a = b as A[]; then that would succeed because you are casting from a more-derived array type to a less-derived array type. You could even use A[] a = (A[]) b; because as would never fail to upcast. Even better would be A[] a = b; because the compiler knows that every B is also an A, therefore every B[] is also an A[].Forego
L
2

This is an answer related to a bounty question asked by @user366312 and not to the original question.

What would be the solution in the case of .NET Framework 2.0?

As far as I know, LINQ was introduced to the.NET framework with version 3.5 back in 2007. So this means it is not possible to use LINQ in .NET Framework 2.0.

Therefore I would use just a regular for-loop and cast each element in the array.

Something like this without testing it:

var newArray = new NewType[myArray.Length];

for (var i = 0; i < myArray.Length; i++)
{
    newArray[i] = (NewType)myArray[i];
}

You can wrap it up in a method like:

public static NewType[] ConvertAll(Vec2[] myArray)
{
    var newArray = new NewType[myArray.Length];

    for (var i = 0; i < myArray.Length; i++)
    {
        newArray[i] = (NewType)myArray[i];
    }

    return newArray;
}

And use it

var newArray = ConvertAll(myArray);
Ligule answered 18/4, 2022 at 10:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.