2012-04-12 6 views
6

Vengo de JavaScript, y sé que { } es un objeto literal, sin necesidad de requerir la llamada new Object; Me pregunto si es lo mismo con C# en la parte {"id",id}, {"saveChangesError",true}.¿Qué característica de C# permite el uso de una notación de tipo "literal de objeto"?

Sé que hay dos características C# aquí, ¿me puede explicar más sobre lo que son?

new RouteValueDictionary() 
{ //<------------------------------[A: what C# feature is this?] -------|| 
    {"id",id}, //<------------------[B: what C# feature is this also?] || 
    {"saveChangesError",true}            || 
}); //<------------------------------------------------------------------|| 
+0

Es la magia simplemente especial en C# para llamar automáticamente algunos métodos ('add' en particular) * * después de que el objeto ha sido creado. –

+0

Para las respuestas: ¿se puede * inicializar la propiedad * mezclar con * inicialización de la colección *? (Esto debería estar presente al explicar la construcción "externa", como podría haber sido: 'nuevo Foo {Bar = Quz}'.) –

+0

@pst: No, ni siquiera en VB.NET, curiosamente ... – Ryan

Respuesta

8

Es una característica única - collection initializers. Al igual que los inicializadores de objetos, solo se puede usar como parte de una expresión de inicialización de objetos, pero básicamente llama a Add con los argumentos que estén presentes, usando llaves para especificar múltiples argumentos, o argumentos individuales a la vez sin llaves adicionales, p. Ej.

var list = new List<int> { 1, 2, 3 }; 

Consulte la sección 7.6.10.3 de la especificación C# 4 para obtener más información.

Tenga en cuenta que el compilador requiere dos cosas de un tipo para que sea utilizado para la recolección de inicializadores:

  • Debe implementar IEnumerable, aunque el compilador no genera ninguna llamada a GetEnumerator
  • Se debe tener sobrecargas apropiadas para un Add método

Por ejemplo:

using System; 
using System.Collections; 

public class Test : IEnumerable 
{ 
    static void Main() 
    { 
     var t = new Test 
     { 
      "hello", 
      { 5, 10 }, 
      { "whoops", 10, 20 } 
     }; 
    } 

    public void Add(string x) 
    { 
     Console.WriteLine("Add({0})", x); 
    } 

    public void Add(int x, int y) 
    { 
     Console.WriteLine("Add({0}, {1})", x, y); 
    } 

    public void Add(string a, int x, int y) 
    { 
     Console.WriteLine("Add({0}, {1}, {2})", a, x, y); 
    } 

    IEnumerator IEnumerable.GetEnumerator()   
    { 
     throw new NotSupportedException(); 
    } 
} 
+0

http://msdn.microsoft.com/en-us/ library/bb531208.aspx – pm100

+2

Tengamos un enlace a la documentación de MSDN en la respuesta, al menos. :) –

+0

@DanJ: Sí, estoy llegando :) –

7

Esa es la sintaxis de inicialización de la colección. Este:

RouteValueDictionary d = new RouteValueDictionary() 
{        //<-- A: what C# feature is this? 
    {"id",id},     //<-- B: what C# feature is this also?  
    {"saveChangesError",true} 
}); 

es básicamente equivalente a esto:

RouteValueDictionary d = new RouteValueDictionary(); 
d.Add("id", id); 
d.Add("saveChangesError", true); 

El compilador reconoce el hecho de que se implementa IEnumerable y tiene un método apropiado Add y utiliza eso.

Ver: http://msdn.microsoft.com/en-us/library/bb531208.aspx

+4

"sintaxis de inicialización del diccionario" hace que suene como C# * ya que un idioma * tiene un conocimiento incorporado de los diccionarios. No es así Funcionará con * cualquier * tipo que implemente 'IEnumerable' y tenga los métodos 'Add' apropiados. –

+1

@JonSkeet: ¿Cómo reconoce el hecho de que es un 'KeyValuePair'? – Ryan

+3

@minitech: No es así. Reconoce el hecho de que hay un método 'Add (clave, valor)'. Vea mi respuesta para un ejemplo de esto. También tenga en cuenta que, en realidad, la variable solo se asigna * después de * las llamadas 'Agregar' - es como si tuviera una variable temporal antes de eso. –

Cuestiones relacionadas