type - string to int c#




Casting directo vs 'como' operador? (12)

Considere el siguiente código:

void Handler(object o, EventArgs e)
{
   // I swear o is a string
   string s = (string)o; // 1
   //-OR-
   string s = o as string; // 2
   // -OR-
   string s = o.ToString(); // 3
}

¿Cuál es la diferencia entre los tres tipos de casting (bueno, el tercero no es un casting, pero obtienes la intención). ¿Cuál debería ser la preferida?


  1. Usar cuando algo debería ser definitivamente la otra cosa.
  2. Utilizar cuando algo podría ser la otra cosa.
  3. Úselo cuando no le importa lo que sea, pero solo desea usar la representación de cadena disponible.

"(cadena) o" dará como resultado una excepción InvalidCastException ya que no hay conversión directa.

"o como cadena" dará como resultado que s sea una referencia nula, en lugar de lanzar una excepción.

"o.ToString ()" no es una conversión de ningún tipo per se, es un método que se implementa por objeto, y por lo tanto de una forma u otra, por cada clase en .net que "hace algo" con la instancia de la clase se llama y devuelve una cadena.

No olvide que para convertir en cadena, también hay Convert.ToString (someType instanceOfThatType) donde someType es uno de un conjunto de tipos, esencialmente los tipos básicos de marcos.


2 es útil para lanzar a un tipo derivado.

Supongamos que a es un animal:

b = a as Badger;
c = a as Cow;

if (b != null)
   b.EatSnails();
else if (c != null)
   c.EatGrass();

Obtendrá una alimentación con un mínimo de lanzamientos.


Al intentar obtener la representación de cadena de cualquier cosa (de cualquier tipo) que pueda ser nula, prefiero la línea de código que se encuentra a continuación. Es compacto, invoca a ToString () y maneja correctamente los nulos. Si o es nulo, s contendrá String.Empty.

String s = String.Concat(o);

La palabra clave as es buena en asp.net cuando utiliza el método FindControl.

Hyperlink link = this.FindControl("linkid") as Hyperlink;
if (link != null)
{
     ...
}

Esto significa que puede operar con la variable escrita en lugar de tener que lanzarla desde un object como lo haría con una conversión directa:

object linkObj = this.FindControl("linkid");
if (link != null)
{
     Hyperlink link = (Hyperlink)linkObj;
}

No es una gran cosa, pero guarda líneas de código y asignación de variables, además es más legible


Las siguientes dos formas de conversión de tipo (conversión) se admiten en C #:

|

(CV

• Convertir el tipo estático de v a c en la expresión dada

• Solo es posible si el tipo dinámico de v es c, o un subtipo de c

• Si no, se lanza una excepción InvalidCastException

|

v como C

• Variante no fatal de (c) v

• Por lo tanto, convierta el tipo estático de v a c en la expresión dada

• Devuelve nulo si el tipo dinámico de v no es c, o un subtipo de c


Parece que los dos son conceptualmente diferentes.

Casting directo

Los tipos no tienen que estar estrictamente relacionados. Se presenta en todo tipo de sabores.

  • Conversión implícita / explícita personalizada: normalmente se crea un nuevo objeto.
  • Tipo de valor implícito: Copie sin perder información.
  • Tipo de valor explícito: se puede perder la copia y la información.
  • Relación IS-A: Cambia el tipo de referencia, de lo contrario lanza una excepción.
  • Mismo tipo: 'Casting es redundante'.

Se siente como si el objeto se va a convertir en otra cosa.

Operador AS

Los tipos tienen una relación directa. Como en:

  • Tipos de referencia: relación IS-A Los objetos son siempre los mismos, solo cambia la referencia.
  • Tipos de valor: Copia de boxeo y tipos anulables.

Se siente como que vas a manejar el objeto de una manera diferente.

Muestras e IL

    class TypeA
    {
        public int value;
    }

    class TypeB
    {
        public int number;

        public static explicit operator TypeB(TypeA v)
        {
            return new TypeB() { number = v.value };
        }
    }

    class TypeC : TypeB { }
    interface IFoo { }
    class TypeD : TypeA, IFoo { }

    void Run()
    {
        TypeA customTypeA = new TypeD() { value = 10 };
        long longValue = long.MaxValue;
        int intValue = int.MaxValue;

        // Casting 
        TypeB typeB = (TypeB)customTypeA; // custom explicit casting -- IL:  call class ConsoleApp1.Program/TypeB ConsoleApp1.Program/TypeB::op_Explicit(class ConsoleApp1.Program/TypeA)
        IFoo foo = (IFoo)customTypeA; // is-a reference -- IL: castclass  ConsoleApp1.Program/IFoo

        int loseValue = (int)longValue; // explicit -- IL: conv.i4
        long dontLose = intValue; // implict -- IL: conv.i8

        // AS 
        int? wraps = intValue as int?; // nullable wrapper -- IL:  call instance void valuetype [System.Runtime]System.Nullable`1<int32>::.ctor(!0)
        object o1 = intValue as object; // box -- IL: box [System.Runtime]System.Int32
        TypeD d1 = customTypeA as TypeD; // reference conversion -- IL: isinst ConsoleApp1.Program/TypeD
        IFoo f1 = customTypeA as IFoo; // reference conversion -- IL: isinst ConsoleApp1.Program/IFoo

        //TypeC d = customTypeA as TypeC; // wouldn't compile
    }

Realmente depende de si sabes si o es una cadena y qué quieres hacer con ella. Si su comentario significa que o realmente es una cadena, preferiría la ola recta (string)o , es poco probable que falle.

La mayor ventaja de usar el cast directo es que cuando falla, obtienes una InvalidCastException , que te dice qué fue lo que salió mal.

Con el operador as , si o no es una cadena, s se establece en null , lo que es útil si no está seguro y desea probar s :

string s = o as string;
if ( s == null )
{
    // well that's not good!
    gotoPlanB();
}

Sin embargo, si no realiza esa prueba, usará s más tarde y se NullReferenceException una NullReferenceException . Estos tienden a ser más comunes y mucho más difíciles de rastrear una vez que ocurren en la naturaleza, ya que casi todas las líneas hacen referencia a una variable y pueden lanzar una. Por otro lado, si está intentando convertir a un tipo de valor (cualquier primitivo, o estructuras como DateTime ), tiene que usar la conversión directa, as que no funcionará.

En el caso especial de convertir a una cadena, cada objeto tiene una ToString , por lo que su tercer método puede estar bien si o no es nulo y cree que el método ToString puede hacer lo que quiera.


Si ya sabe a qué tipo se puede convertir, use un modelo de estilo C:

var o = (string) iKnowThisIsAString; 

Tenga en cuenta que solo con una conversión de estilo C se puede realizar una coacción de tipo explícita.

Si no sabe si es el tipo deseado y lo usará si lo es, use como palabra clave:

var s = o as string;
if (s != null) return s.Replace("_","-");

//or for early return:
if (s==null) return;

Tenga en cuenta que como no llamará a ningún tipo de operadores de conversión. Solo será no nulo si el objeto no es nulo y de forma nativa del tipo especificado.

Use ToString () para obtener una representación de cadena legible para cualquier objeto, incluso si no se puede convertir en cadena.


Todas las respuestas dadas son buenas, si puedo agregar algo: para usar directamente los métodos y las propiedades de la cadena (por ejemplo, ToLower) no puede escribir:

(string)o.ToLower(); // won't compile

solo puedes escribir

((string)o).ToLower();

pero podrías escribir en su lugar:

(o as string).ToLower();

La opción as es más legible (al menos en mi opinión).


string s = (string)o; // 1

Lanza la InvalidCastException si o no es una string . De lo contrario, asigna o a s , incluso si o es null .

string s = o as string; // 2

Asigna null a s si o no es una string o si o es null . Por este motivo, no puede usarlo con tipos de valor (el operador nunca podría devolver un null en ese caso). De lo contrario, asigna o a s .

string s = o.ToString(); // 3

Provoca una NullReferenceException si o es null . Asigna lo que o.ToString() devuelve a s , sin importar qué tipo o es.

Use 1 para la mayoría de las conversiones, es simple y directo. Tiendo a casi nunca usar 2 ya que si algo no es del tipo correcto, generalmente espero que ocurra una excepción. Solo he visto la necesidad de este tipo de funcionalidad de retorno nulo con bibliotecas mal diseñadas que usan códigos de error (por ejemplo, return null = error, en lugar de usar excepciones).

3 no es un lanzamiento y es solo una invocación de método. Úselo para cuando necesite la representación de cadena de un objeto no de cadena.


string s = o as string; // 2

Se prefiere, ya que evita la penalización de rendimiento de doble casting.







casting