C#中的运行时转换?

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)

这太可怜了.:(