C# Convert object of type array to T, where T is an array?
It'd be really good if I could get an object to array conversion working.
Steps:
- We get passed an array from an external source. The array is boxed in an object. Typically the object is an int[] or a double[], but we normally want double[].
- Convert it to an array of Type T.
- return the converted type.
For starters, this works fine
double[] r=Array.ConvertAll<int,double>((int[])o,Convert.ToDouble)
but this doesn't (assume that T is "double") e.g. double[] R=getValue(o);
public T[] getValue<T>(object o){
// ... some logic...
return (T[])Array.ConvertAll<int,double>((int[])o,Convert.ToDouble)
Is there a where constraint that can be used? Array is a "Special Object", so we can't use that as a constraint.
Is this possible in .net without resorting to IL? Is it possil开发者_如何学Pythonbe if we do resort to IL?
thanks, -Steven
This worked for me:
public T[] GetValue<T>(object o)
{
Converter<int, T> c = new Converter<int, T>(input => (T)System.Convert.ChangeType(input, typeof(T)));
return (T[])Array.ConvertAll<int, T>((int[])o, c);
}
I hope this helps!
Try this:
public T[] getValue<T>(object o)
{
return (T[])Convert.ChangeType(o, typeof(T[]));
}
Use like this:
object doubleArr = new Double[] {1.3, 1.5, 1.7};
var returnedValue = getValue<double>(doubleArr);
Note that if you pass in the wrong type for the template, it will fail at run time
-- Deleted previous content
Sorry, I did not see the Convert.ToDouble which will of course not compile. To be able to handle any type of T you have to pass a convert callback to getValue
.
Something like this should do the job:
public T[] getValue<T>(object o, Converter<int, T> converter)
{
// ... some logic...
return (T[])Array.ConvertAll<int,T>((int[])o, converter)
}
Usage:
double[] result = getValue<double>(o, (i) => Convert.ToDouble(i));
well all three of the above answers work. Awesome. Thanks very much.
A question: in the notation above Convert.ToDouble
in the caller became (i) => Convert.ToDouble(i)
. Is the notation equivilent?
I'm new around here... am I supposed to accept an answer somehow? Not sure if I can because when I posted the question I wasn't registered.
In an extension to the above answers, I got this to work which is very neat solution:
public T[,,] getValue_3d<T>(object o) {
return (T[,,])Convert.ChangeType(o,typeof(T[,,]));
}
usage:
object doubleArr=new Double[,,] { { { 1, 2, 3 }, { 4, 5, 6 } },
{ { 7, 8, 9 }, { 10, 11, 12 } } };
double[,,] returnedValue=getValue_3d<double>(doubleArr);
One of the things I tried originally was to have T (where T is an n-rank array), get the element type, and then do the conversion. It didn't work too well when it came to returning the value from the function.
To do this even more neatly, it'd be nice if we could do overloads with function return values... but to the best of my knowledge this isn't possible in C# by design. Perhaps there's a another trick. Also tried TIn + TOut to no avail (TIn is double, and TOut is double[]
/ double[,]
/ double[,,]
.
Thanks again.
Here's yet another solution :D
public T[] getValue<T>(object o) => o as T[];
However, this might return a null
value because of how as
works (instead of crashing --- which might be a good thing?). as
works at runtime, so be careful with how you use it, but if you're using object
s then you're already navigating dangerous waters.
I like doing the following so that I don't have to deal with null
s everywhere.
public T[] getValue<T>(object o) => o as T[] ?? Array.Empty<T>();
Also, this way you don't have to use another level of indirection :3
EDIT: I also noticed that you said that
Typically the object is an int[] or a double[], but we normally want double[].
if you know that you only want those two types then you could also be more explicit:
public T[] getValue<T>(object o) => o switch {
int[] array => array as T[],
double[] array => array as T[],
var _ => null,
} ?? Array.Empty<T>();
Maybe it's more of a pain to maintain, but it's a bit more explicit. Instead of returning null
maybe you could throw and error also to make sure you're not passing the wrong type.
I hope this helps someone :3
精彩评论