我有一个函数可以生成包含不同数据的对象(该函数根据类型用随机数据填充对象)。该函数返回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;
}
}
答案 0 :(得分:6)
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());
}