C# Language
Anonimowe typy
Szukaj…
Tworzenie anonimowego typu
Ponieważ anonimowe typy nie są nazwane, zmienne tych typów muszą być niejawnie wpisane ( var
).
var anon = new { Foo = 1, Bar = 2 };
// anon.Foo == 1
// anon.Bar == 2
Jeśli nazwy członków nie zostaną określone, zostaną ustawione na nazwę właściwości / zmiennej użytej do zainicjowania obiektu.
int foo = 1;
int bar = 2;
var anon2 = new { foo, bar };
// anon2.foo == 1
// anon2.bar == 2
Należy zauważyć, że nazwy można pominąć tylko wtedy, gdy wyrażenie w anonimowej deklaracji typu jest prostym dostępem do właściwości; w przypadku wywołań metod lub bardziej złożonych wyrażeń należy podać nazwę właściwości.
string foo = "some string";
var anon3 = new { foo.Length };
// anon3.Length == 11
var anon4 = new { foo.Length <= 10 ? "short string" : "long string" };
// compiler error - Invalid anonymous type member declarator.
var anon5 = new { Description = foo.Length <= 10 ? "short string" : "long string" };
// OK
Anonimowy kontra dynamiczny
Anonimowe typy pozwalają na tworzenie obiektów bez konieczności wcześniejszego definiowania ich typów, przy zachowaniu statycznego sprawdzania typów.
var anon = new { Value = 1 };
Console.WriteLine(anon.Id); // compile time error
I odwrotnie, dynamic
ma dynamiczne sprawdzanie typu, wybierając błędy czasu wykonywania zamiast błędów czasu kompilacji.
dynamic val = "foo";
Console.WriteLine(val.Id); // compiles, but throws runtime error
Metody ogólne z typami anonimowymi
Metody ogólne pozwalają na użycie typów anonimowych poprzez wnioskowanie o typie.
void Log<T>(T obj) {
// ...
}
Log(new { Value = 10 });
Oznacza to, że wyrażeń LINQ można używać z typami anonimowymi:
var products = new[] {
new { Amount = 10, Id = 0 },
new { Amount = 20, Id = 1 },
new { Amount = 15, Id = 2 }
};
var idsByAmount = products.OrderBy(x => x.Amount).Select(x => x.Id);
// idsByAmount: 0, 2, 1
Tworzenie instancji typów ogólnych z typami anonimowymi
Korzystanie z ogólnych konstruktorów wymagałoby nazw anonimowych typów, co nie jest możliwe. Alternatywnie można zastosować metody ogólne, aby umożliwić wnioskowanie typu.
var anon = new { Foo = 1, Bar = 2 };
var anon2 = new { Foo = 5, Bar = 10 };
List<T> CreateList<T>(params T[] items) {
return new List<T>(items);
}
var list1 = CreateList(anon, anon2);
W przypadku List<T>
niejawnie wpisane tablice mogą być konwertowane na List<T>
za pomocą metody LINQ ToList
:
var list2 = new[] {anon, anon2}.ToList();
Anonimowa równość typów
Równość typu anonimowego jest podawana przez metodę instancji Equals
. Dwa obiekty są równe, jeśli mają ten sam typ i równe wartości (poprzez a.Prop.Equals(b.Prop)
) dla każdej właściwości.
var anon = new { Foo = 1, Bar = 2 };
var anon2 = new { Foo = 1, Bar = 2 };
var anon3 = new { Foo = 5, Bar = 10 };
var anon3 = new { Foo = 5, Bar = 10 };
var anon4 = new { Bar = 2, Foo = 1 };
// anon.Equals(anon2) == true
// anon.Equals(anon3) == false
// anon.Equals(anon4) == false (anon and anon4 have different types, see below)
Dwa anonimowe typy są uważane za takie same wtedy i tylko wtedy, gdy ich właściwości mają tę samą nazwę i typ i występują w tej samej kolejności.
var anon = new { Foo = 1, Bar = 2 };
var anon2 = new { Foo = 7, Bar = 1 };
var anon3 = new { Bar = 1, Foo = 3 };
var anon4 = new { Fa = 1, Bar = 2 };
// anon and anon2 have the same type
// anon and anon3 have diferent types (Bar and Foo appear in different orders)
// anon and anon4 have different types (property names are different)
Tablice niejawnie wpisane
Tablice typów anonimowych mogą być tworzone z niejawnym pisaniem.
var arr = new[] {
new { Id = 0 },
new { Id = 1 }
};