Gar*_*son 5 c# generics casting runtime
我正在从自定义数据格式中读取数据,该格式在概念上将数据存储在表中.每列可以具有不同的类型.这些类型特定于文件格式并映射到C#类型.
我有一个Column类型,它封装了一个列的想法,通用参数T表示列中的C#类型.Column.FormatType根据格式类型指示类型.所以要读取列的值,我有一个简单的方法:
protected T readColumnValue<T>(Column<T> column)
{
switch (column.FormatType)
{
case FormatType.Int:
return (T)readInt();
}
}
Run Code Online (Sandbox Code Playgroud)
多么简单优雅!现在我所要做的就是:
Column<int> column=new Column<int>(...)
int value=readColumnValue(column);
Run Code Online (Sandbox Code Playgroud)
类型T的上述强制转换将在Java中起作用(尽管有警告),并且由于擦除,在调用者实际使用该值之前不会对该强制转换进行求值 - 此时如果强制转换将抛出ClassCastException不对.
这在C#中不起作用.但是,因为C#不会丢弃泛型类型,所以应该可以使它更好!我似乎可以在运行时询问T的类型:
Type valueType=typeof(T);
Run Code Online (Sandbox Code Playgroud)
伟大的---所以我有我将要回归的价值类型.我该怎么办?如果这是Java,因为存在一个执行运行时强制转换的Class.Cast方法,我将无家可归!(因为每个Java Class类都有一个泛型类型参数,指示该类是否也适用于它也可以提供编译时类型的安全性.)以下内容来自我的梦想世界,其中C#Type类的工作方式类似于Java Class类:
protected T readColumnValue<T>(Column<T> column)
{
Type<T> valueType=typeof(T);
switch (column.FormatType)
{
case FormatType.Int:
return valueType.Cast(readInt());
}
}
Run Code Online (Sandbox Code Playgroud)
显然没有Type.Cast()---所以我该怎么办?
(是的,我知道有一个Convert.ChangeType()方法,但这似乎执行转换,而不是简单的转换.)
更新:所以如果没有使用(T)(对象)readInt()的装箱/拆箱,这似乎是不可能的.但这是不可接受的.这些文件非常大 - 例如80MB.假设我想阅读整列数值.我有一个优雅的小方法,使用泛型并调用上面的方法,如下所示:
public T[] readColumn<T>(Column<T> column, int rowStart, int rowEnd, T[] values)
{
... //seek to column start
for (int row = rowStart; row < rowEnd; ++row)
{
values[row - rowStart] = readColumnValue(column);
... //seek to next row
Run Code Online (Sandbox Code Playgroud)
数百万价值的拳击/拆箱?这听起来不太好.我觉得很荒谬,我将不得不扔掉泛型并使用readColumnInt(),readColumnFloat()等,并重现所有这些代码只是为了防止装箱/取消装箱!
public int[] readColumnInt(Column<int> column, int rowStart, int rowEnd, int[] values)
{
... //seek to column start
for (int row = rowStart; row < rowEnd; ++row)
{
values[row - rowStart] = readInt();
... //seek to next row
public float[] readColumnFloat(Column<float> column, int rowStart, int rowEnd, float[] values)
{
... //seek to column start
for (int row = rowStart; row < rowEnd; ++row)
{
values[row - rowStart] = readFloat();
... //seek to next row
Run Code Online (Sandbox Code Playgroud)
这太可怜了.:(