Pregunta

Considerar:

object o = 123456U;
ulong l = (ulong) o; // fails

Pero esto:

object o = 123456U;
ulong l = (ulong) (uint) o; // succeeds

El verdadero problema que tengo es que me gustaría tener una función que dependiera de un tipo de parámetro, los procesa de manera diferente. Como:

void foo(object o)
{
switch (Type.GetTypeCode(o.GetType()))
   {
      case TypeCode.UInt32:
      case TypeCode.UInt64:
      ulong l = (ulong) o;
      RunUnsignedIntVersion(l);
      break;
      case TypeCode.Int32:
      case TypeCode.Int64:
      long n = (long) o;
      RunSignedVersion(n);
      break;
   }
}

Y no puedes hacer las siguientes llamadas:

foo(123456U);
foo(123456);

Sé que hay formas de hacer esto usando genéricos. Pero estoy usando .NET Micro Framework y los genéricos no son compatibles. Pero se admiten cualquier característica específica del compilador C# 3.0, incluidas funciones anónimas.

Editar Me gustaría evitar tener que manejar cada tipo por separado. ¿Hay alguna forma de hacer esto y aún tiene un parámetro de tipo de objeto?

¿Fue útil?

Solución

Las operaciones del Unbox admiten solo el Unbox, no cualquier coerción que pueda esperar.

Si bien esto puede ser frustrante, vale la pena señalar que arreglar esto

  1. hacer unboxing importantemente más caro
  2. posiblemente complicar el lenguaje debido a casos de borde desagradable en la selección de sobrecarga de métodos

Entre otros, para alguna explicación en profundidad, Eric Lippert es, como siempre, mas instructivo

Si te importa el rendimiento, la única forma efectiva de hacerlo es (como señala Jimmy)

case TypeCode.Int32:
    RunSignedVersion((int) o);
    break;
case TypeCode.Int64:
    long n = (long) o;
    RunSignedVersion(n);
    break;

Esto no parece demasiado oneroso.

Si esto es demasiado doloroso, entonces puede hacer uso de Convert.Toint64 o Convert.TouInt64 () con el costo asociado.

void foo(object o)
{
   switch (Type.GetTypeCode(o.GetType()))
   {
      case TypeCode.UInt32:
      case TypeCode.UInt64:
          ulong l = Convert.ToUInt64(o);
          RunUnsignedIntVersion(l);
          break;
      case TypeCode.Int32:
      case TypeCode.Int64:
          long n = Convert.ToInt64(o);
          RunSignedVersion(n);
          break;
   }
}

Si la conversión no está disponible, aquí está la fuente del rotor para los métodos relevantes:

    [CLSCompliant(false)]   
    public static ulong ToUInt64(object value) {
        return value == null? 0: ((IConvertible)value).ToUInt64(null);
    }

    [CLSCompliant(false)]   
    public static long ToInt64(object value) {
        return value == null? 0: ((IConvertible)value).ToInt64(null);
    }

Iconvertible es compatible como una interfaz en el marco compacto, supongo que esto funcionaría, pero no lo he probado.

Si desea el Microframework, sugiero que simplemente implementar las opciones de conversión por tipo es lo mejor que puede hacer. La API es Tan escaso que realmente no hay mucho más posible. También sugeriría que cualquier cosa basada en el boxeo sea arriesgado, ya que esta es una sobrecarga de asignación significativa en un entorno muy limitado de memoria.

Si está intentando implementar un String.format () por igual, ¿ha considerado System.ext.text.stringbuilder.appendformat seguido de una tostración?

Otros consejos

  case TypeCode.Int32:
    RunSignedVersion((int) o);
    break;
  case TypeCode.Int64:
    long n = (long) o;
    RunSignedVersion(n);
    break;

La razón por la que no puede Unbox como int es porque el unboxing y el casting son dos operaciones diferentes que comparten el mismo operador.

Esto se debe a que solo puede desempaquetarse del mismo tipo que originalmente estaba en caja (o a la versión anulable de ese tipo).

Por ejemplo, un cuadro byte solo se puede desempaquetar a byte o byte?, un en caja int solo se puede desempaquetar a int o int?, un en caja long solo se puede desempaquetar a long o long? etcétera etcétera.

Puede crear un método de extensión como ese:

public static class ConversionExtensions
{
    public static ulong ToUInt64(this object value)
    {
        return ((IConvertible)value).ToUInt64();
    }
}

Luego podrías usarlo de la siguiente manera:

object o = 123456U;
ulong l = o.ToUInt64();
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top