在C#上从object []转换为double []

时间:2015-08-05 13:46:19

标签: c# arrays dynamic casting

我有一个函数可以生成包含不同数据的对象(该函数根据类型用随机数据填充对象)。该函数返回object[],因为该类型仅在运行时知道(并且它作为参数传递给函数)。

double[] values;

values = factory.GetData(typeof(double), 10);

不幸的是我遇到了编译错误:

  

无法从object []转换为double []。

如何以编程方式投射object[]

编辑:

这是原始功能:

    public object[] GetData(Type type, int howMany)
    {
        var data = new List<object>();

        for (var i = 0; i < howMany; i++)
        {
            data.Add(Convert.ChangeType(GetRandom(type), type));
        }

        return data.ToArray();
    }

其中GetRandom()创建一个type类型的对象并为其分配一个随机值(随机int,随机字符串,随机双精度,仅基本类型)

这是GetRandom()函数:

   public T GetRandom<T>()
    {
        var type = typeof(T);

        if (type == typeof(int))
        {
            return prng.Next(0, int.MaxValue);
        }

        if (type == typeof(double))
        {
            return prng.NextDouble();
        }

        if (type == typeof(string))
        {
            return GetString(MinStringLength, MaxStringLength);
        }

        if (type == typeof(DateTime))
        {
            var tmp = StartTime;
            StartTime += new TimeSpan(Interval * TimeSpan.TicksPerMillisecond);
            return tmp;
        }
    }

5 个答案:

答案 0 :(得分:6)

使用Array.ConvertAll

values =  Array.ConvertAll(factory.GetData(typeof(double), 10), item => (double)item);

示例:

object[] input = new object[]{1.0, 2.0, 3.0};
double[] output = Array.ConvertAll(input, element => (double)element); // [1.0, 2.0, 3.0]

请注意,如果其中一个项目无法投放,则可能会获得InvalidCastException

答案 1 :(得分:3)

你可以:

values =  factory.GetData(typeof(double), 10).Cast<double>().ToArray();

答案 2 :(得分:3)

如果factory.GetData返回double对象的数组,则可以使用:

src.zip

答案 3 :(得分:1)

假设GetData 确实将双打框作为数组,您可以使用Cast()将所有元素转换为加倍:

values=factory.GetData(typeof(double), 10).Cast<double>().ToArray();

或者您可以使用OfType()过滤掉 double的值

values=factory.GetData(typeof(double), 10).OfType<double>().ToArray();

更好的选择是将GetData重写为通用方法并返回T[]

答案 4 :(得分:1)

现在所有的答案(大多数)实际上回答的问题是,实际上并没有谈论使用泛型。现在这可能不适合您的直接账单,但可以很容易地添加来解决问题,并且不需要来自调用应用程序的知识如何理解返回值。

这很简单。只需定义一个接受通用类型的重载(注意T

public T[] GetData<T>(int count)
{
    Type tType = typeof(T);
    //.. TODO: Generate our array.. anyway you wish..
    List<T> list = new List<T>();
    for (int i = 0; i < count; i++)
        list.Add(Activator.CreateInstance<T>());
    return list.ToArray();
}

所以这是一个基本的例子,可以通过以下方式调用:

Factory factory = new Factory();
var arr = factory.GetData<double>(10); //returns a typed array of double

现在从调用者的角度来看,我们知道我们正在接收的数据被输入double或它们提供的类型。

这是您最初提问的替代方案。但是,如果您的对象数组并不总是最初请求的类型,那么这将无效。

修改

定义数组实际上取决于您如何定义对象,但我们只需要采用您的初始概念并将其调整为相同的内容:

public T[] GetData<T>(int count)
{
    Type tType = typeof(T);
    //.. TODO: Generate our array.. anyway you wish..
    List<T> list = new List<T>();
    for (int i = 0; i < count; i++)
        list.Add((T)GetRandom(tType));
    return list.ToArray();
}

在新示例中,我们假设方法GetRandom()将返回请求的类型。请求的类型是基于typereference(typeparam)T的通用类型。我们可以通过调用typeof(T)来获取实际类型。现在,在此示例中,我们只是直接转换GetRandom()对象响应(我假设GetRandom()返回object类型。

最终修改

如评论中所述,您可以将object GetRandom(Type type)更改为T GetRandom<T>()。这将允许您为随机生成特定类型。我建议阅读Generics https://msdn.microsoft.com/en-us/library/512aeb7t.aspx

现在有一件事情并不是很明显,那就是你所说的通用名称取决于你。您不必使用T,并且可以在一个方法调用中使用多个泛型,就像您可能已经使用的许多方法一样。

**最终决赛编辑**

为了详细说明如何将GetRandom方法更改为泛型,我们仍然必须使用类型object,它实际上是唯一允许任何类型的直接装箱转换的方法。您可以使用as关键字,但这可能会留下其他问题。现在GetRandom(Type type)方法返回该类型的随机对象。如上所述,这仅限于几种类型,所以我们只举一个例子。

首先要了解的是如何处理我们的各种类型。现在我个人想定义一个界面。因此,我们要为所有随机类型定义一个接口来继承。如下:

interface IRandomTypeBuilder
{
    object GetNext();
}

使用GetNext()方法返回随机类型实体的简单接口。这将返回基于通用参数T的类型化响应。

现在这个界面的一些简单实现。

class DoubleRandomBuilder : IRandomTypeBuilder
{
    static Random rng = new Random();        
    public object GetNext()
    {
        return rng.NextDouble() * rng.Next(0, 1000);
    }
}

class IntRandomBuilder : IRandomTypeBuilder
{
    static Random rng = new Random();
    public object GetNext()
    {
        return rng.Next(int.MinValue, int.MaxValue);
    }
}

class StringRandomBuilder : IRandomTypeBuilder
{
    static Random rng = new Random();
    static string aplha = "abcdefghijklmnopqrstuvwxyz";
    public object GetNext()
    {
        string next = "";
        for (int i = rng.Next(4, 10), j = i + rng.Next(1, 10); i < j; i++)
            next += aplha[rng.Next(0, aplha.Length)];
        return next;
    }
}

class BoolRandomBuilder : IRandomTypeBuilder
{
    static Random rng = new Random();
    public object GetNext()
    {
        return rng.Next(0, 2) % 2 == 0;
    }
}

是的,这些非常简单,但我们有4种不同的类型,它们都定义GetNext()方法并返回该类型的随机值。现在我们可以定义GetRandom<T>()方法。

public T GetRandom<T>()
{
    Type tType = typeof(T);
    IRandomTypeBuilder typeGenerator = null;
    if (tType == typeof(double))
        typeGenerator = new DoubleRandomBuilder();
    else if (tType == typeof(int))
        typeGenerator = new IntRandomBuilder();
    else if (tType == typeof(string))
        typeGenerator = new StringRandomBuilder();
    else if (tType == typeof(bool))
        typeGenerator = new BoolRandomBuilder();
    return (T)(typeGenerator == null ? default(T) : typeGenerator.GetNext());
}