Inicjatory obiektów: typy nazwane i anonimowe (Visual Basic)

Inicjatory obiektów umożliwiają określanie właściwości obiektu złożonego przy użyciu pojedynczego wyrażenia. Mogą służyć do tworzenia wystąpień nazwanych typów i typów anonimowych.

Deklaracje

Deklaracje wystąpień nazwanych i anonimowych typów mogą wyglądać niemal identycznie, ale ich skutki nie są takie same. Każda kategoria ma własne możliwości i ograniczenia. W poniższym przykładzie pokazano wygodny sposób deklarowania i inicjowania wystąpienia nazwanej klasy , Customerprzy użyciu listy inicjatora obiektów. Zwróć uwagę, że nazwa klasy jest określona po słowie kluczowym New.

Dim namedCust = New Customer With {.Name = "Terry Adams"}

Typ anonimowy nie ma nazwy użytecznej. W związku z tym wystąpienie typu anonimowego nie może zawierać nazwy klasy.

Dim anonymousCust = New With {.Name = "Hugo Garcia"}

Wymagania i wyniki tych dwóch deklaracji nie są takie same. Customer W przypadku namedCustklasy , która ma Name już właściwość, musi już istnieć, a deklaracja tworzy wystąpienie tej klasy. W przypadku anonymousCustprogramu kompilator definiuje nową klasę, która ma jedną właściwość, ciąg o nazwie Namei tworzy nowe wystąpienie tej klasy.

Typy nazwane

Inicjatory obiektów zapewniają prosty sposób wywoływania konstruktora typu, a następnie ustawiania wartości niektórych lub wszystkich właściwości w jednej instrukcji. Kompilator wywołuje odpowiedni konstruktor dla instrukcji: konstruktor bez parametrów, jeśli nie są prezentowane żadne argumenty, lub konstruktor sparametryzowany, jeśli jeden lub więcej argumentów jest wysyłanych. Następnie określone właściwości są inicjowane w kolejności, w której są prezentowane na liście inicjatorów.

Każda inicjalizacja na liście inicjatora składa się z przypisania wartości początkowej do składowej klasy. Nazwy i typy danych składowych są określane podczas definiowania klasy. W poniższych przykładach Customer klasa musi istnieć i musi mieć elementy członkowskie o nazwie Name i City które mogą akceptować wartości ciągów.

Dim cust0 As Customer = New Customer With {.Name = "Toni Poe", 
                                           .City = "Louisville"}

Alternatywnie możesz uzyskać ten sam wynik, używając następującego kodu:

Dim cust1 As New Customer With {.Name = "Toni Poe", 
                                .City = "Louisville"}

Każda z tych deklaracji jest równoważna poniższemu przykładowi, który tworzy Customer obiekt przy użyciu konstruktora bez parametrów, a następnie określa początkowe wartości właściwości Name i City przy użyciu With instrukcji .

Dim cust2 As New Customer()
With cust2
    .Name = "Toni Poe"
    .City = "Louisville"
End With

Customer Jeśli klasa zawiera sparametryzowany konstruktor, który umożliwia wysyłanie w wartości dla Name, na przykład, można również zadeklarować i zainicjować Customer obiekt w następujący sposób:

Dim cust3 As Customer = 
    New Customer("Toni Poe") With {.City = "Louisville"}
' --or--
Dim cust4 As New Customer("Toni Poe") With {.City = "Louisville"}

Nie trzeba inicjować wszystkich właściwości, jak pokazano w poniższym kodzie.

Dim cust5 As Customer = New Customer With {.Name = "Toni Poe"}

Jednak lista inicjowania nie może być pusta. Niezainicjowane właściwości zachowują wartości domyślne.

Wnioskowanie typów z nazwanymi typami

Kod deklaracji cust1 można skrócić, łącząc inicjatory obiektów i wnioskowanie typu lokalnego. Dzięki temu można pominąć klauzulę As w deklaracji zmiennej. Typ danych zmiennej jest wnioskowany z typu obiektu utworzonego przez przypisanie. W poniższym przykładzie typ to cust6Customer.

Dim cust6 = New Customer With {.Name = "Toni Poe", 
                               .City = "Louisville"}

Uwagi dotyczące nazwanych typów

  • Nie można zainicjować składowej klasy więcej niż jeden raz na liście inicjatorów obiektów. Deklaracja powoduje cust7 błąd.

    '' This code does not compile because Name is initialized twice.
    ' Dim cust7 = New Customer With {.Name = "Toni Poe", 
    '                                .City = "Louisville",
    '                                .Name = "Blue Yonder Airlines"}
    
  • Element członkowski może służyć do inicjowania samego lub innego pola. Jeśli dostęp do elementu członkowskiego jest uzyskiwany przed jego zainicjowaniem, jak w poniższej deklaracji dla cust8, zostanie użyta wartość domyślna. Pamiętaj, że gdy deklaracja używająca inicjatora obiektu jest przetwarzana, pierwszą rzeczą, która się dzieje, jest wywoływanie odpowiedniego konstruktora. Następnie poszczególne pola na liście inicjatorów są inicjowane. W poniższych przykładach wartość domyślna parametru Name jest przypisywana dla cust8elementu , a zainicjowana wartość jest przypisywana w pliku cust9.

    Dim cust8 = New Customer With {.Name = .Name & ", President"}
    Dim cust9 = New Customer With {.Name = "Toni Poe", 
                                   .Title = .Name & ", President"}
    

    W poniższym przykładzie użyto sparametryzowanego konstruktora z cust3 i cust4 do deklarowania i inicjowania cust10 i cust11.

    Dim cust10 = New Customer("Toni Poe") With {.Name = .Name & ", President"}
    ' --or--
    Dim cust11 As New Customer("Toni Poe") With {.Name = .Name & ", President"}
    
  • Inicjatory obiektów można zagnieżdżać. W poniższym przykładzie jest to klasa, AddressClass która ma dwie właściwości, City i State, a Customer klasa ma Address właściwość, która jest wystąpieniem AddressClassklasy .

    Dim cust12 = 
        New Customer With {.Name = "Toni Poe", 
                           .Address = 
                               New AddressClass With {.City = "Louisville", 
                                                      .State = "Kentucky"}}
    Console.WriteLine(cust12.Address.State)
    
  • Lista inicjowania nie może być pusta.

  • Zainicjowane wystąpienie nie może być typu Obiekt.

  • Inicjowane składowe klasy nie mogą być współużytkowanymi elementami członkowskimi, członkami tylko do odczytu, stałymi ani wywołaniami metod.

  • Nie można indeksować ani kwalifikowanych składowych klasy. W poniższych przykładach występują błędy kompilatora:

    '' Not valid.

    ' Dim c1 = New Customer With {.OrderNumbers(0) = 148662}

    ' Dim c2 = New Customer with {.Address.City = "Springfield"}

Typy anonimowe

Typy anonimowe używają inicjatorów obiektów do tworzenia wystąpień nowych typów, które nie są jawnie definiowane i nazwa. Zamiast tego kompilator generuje typ zgodnie z właściwościami wyznaczanymi na liście inicjatora obiektów. Ponieważ nazwa typu nie jest określona, jest nazywana typem anonimowym. Na przykład porównaj następującą deklarację z wcześniejszą deklaracją dla cust6elementu .

Dim cust13 = New With {.Name = "Toni Poe", 
                       .City = "Louisville"}

Jedyną różnicą jest to, że żadna nazwa nie jest określona po New dla typu danych. Jednak to, co się dzieje, jest zupełnie inne. Kompilator definiuje nowy typ anonimowy, który ma dwie właściwości i NameCity, i tworzy wystąpienie z określonymi wartościami. Wnioskowanie typu określa typy Name i City w przykładzie jako ciągi.

Uwaga

Nazwa typu anonimowego jest generowana przez kompilator i może się różnić od kompilacji do kompilacji. Kod nie powinien używać ani polegać na nazwie typu anonimowego.

Ponieważ nazwa typu jest niedostępna, nie można użyć As klauzuli w celu zadeklarowania cust13wartości . Jego typ musi być wywnioskowany. Bez użycia opóźnionego powiązania ogranicza to użycie typów anonimowych do zmiennych lokalnych.

Typy anonimowe zapewniają krytyczną obsługę zapytań LINQ. Aby uzyskać więcej informacji na temat używania typów anonimowych w zapytaniach, zobacz Typy anonimowe i Wprowadzenie do LINQ w Visual Basic.

Uwagi dotyczące typów anonimowych

  • Zazwyczaj wszystkie lub większość właściwości w deklaracji typu anonimowego będą właściwościami klucza, które są wskazywane przez wpisanie słowa kluczowego Key przed nazwą właściwości.

    
    Dim anonymousCust1 = New With {Key .Name = "Hugo Garcia", 
                                   Key .City = "Louisville"}
    

    Aby uzyskać więcej informacji na temat właściwości klucza, zobacz Klucz.

  • Podobnie jak nazwane typy, listy inicjatorów dla definicji typów anonimowych muszą zadeklarować co najmniej jedną właściwość.

    Dim anonymousCust = New With {.Name = "Hugo Garcia"}
    
  • Po zadeklarowaniu wystąpienia typu anonimowego kompilator generuje zgodną definicję typu anonimowego. Nazwy i typy danych właściwości są pobierane z deklaracji wystąpienia i są dołączane przez kompilator w definicji. Właściwości nie są nazwane i zdefiniowane z wyprzedzeniem, ponieważ byłyby przeznaczone dla nazwanego typu. Ich typy są wnioskowane. Nie można określić typów danych właściwości przy użyciu klauzuli As .

  • Typy anonimowe mogą również określać nazwy i wartości ich właściwości na kilka innych sposobów. Na przykład właściwość typu anonimowego może przyjmować zarówno nazwę, jak i wartość zmiennej albo nazwę i wartość właściwości innego obiektu.

    ' Create a variable, Name, and give it an initial value.
    Dim Name = "Hugo Garcia"
    
    ' Variable anonymousCust2 will have one property, Name, with 
    ' "Hugo Garcia" as its initial value.
    Dim anonymousCust2 = New With {Key Name}
    
    ' The next declaration uses a property from namedCust, defined
    ' in an earlier example. After the declaration, anonymousCust3 will
    ' have one property, Name, with "Terry Adams" as its value.
    Dim anonymousCust3 = New With {Key namedCust.Name}
    

    Aby uzyskać więcej informacji na temat opcji definiowania właściwości w typach anonimowych, zobacz How to: Infer Property Names and Types in Anonymous Type Deklaracje.

Zobacz też