Genel Kavramlar

Bu bölüm, Microsoft Visual Basic dilinin semantiğini anlamak için gereken çeşitli kavramları kapsar. Kavramların çoğu Visual Basic programcıları veya C/C++ programcıları hakkında bilgi sahibi olmalıdır, ancak kesin tanımları farklı olabilir.

Bildirim

Visual Basic programı adlandırılmış varlıklardan oluşur. Bu varlıklar bildirimler aracılığıyla tanıtılır ve programın "anlamını" temsil eder.

En üst düzeyde, ad alanları iç içe ad alanları ve türler gibi diğer varlıkları düzenleyen varlıklardır. Türler , değerleri açıklayan ve yürütülebilir kod tanımlayan varlıklardır. Türler iç içe türler ve tür üyeleri içerebilir. Tür üyeleri sabitler, değişkenler, yöntemler, işleçler, özellikler, olaylar, numaralandırma değerleri ve oluşturuculardır.

Diğer varlıkları içerebilen bir varlık bir bildirim alanı tanımlar. Varlıklar, bildirimler veya devralma yoluyla bir bildirim alanına eklenir; içeren bildirim alanı, varlıkların bildirim bağlamı olarak adlandırılır. Bildirim alanında bir varlığın bildirim alanına bildirilmesi, daha fazla iç içe varlık bildirimi içerebilen yeni bir bildirim alanı tanımlar; bu nedenle, bir programdaki bildirimler bir bildirim alanları hiyerarşisi oluşturur.

Aşırı yüklenmiş tür üyeleri dışında, bildirimlerin aynı türdeki aynı adlandırılmış varlıkları aynı bildirim bağlamına eklemesi geçersizdir. Ayrıca, bir bildirim alanı hiçbir zaman aynı ada sahip farklı türde varlıklar içermeyebilir; örneğin, bildirim alanı hiçbir zaman aynı ada sahip bir değişken ve yöntem içermeyebilir.

Not. Diğer dillerde aynı ada sahip farklı türde varlıklar içeren bir bildirim alanı oluşturmak mümkün olabilir (örneğin, dil büyük/küçük harfe duyarlıysa ve büyük/küçük harfe göre farklı bildirimlere izin veriyorsa). Bu durumda, en erişilebilir varlık bu ada bağlı olarak kabul edilir; birden fazla varlık türü en erişilebilir durumdaysa ad belirsizdir. Public, değerinden Protected Frienddaha erişilebilir, veya Frienddeğerinden Protected daha erişilebilir ve Protected veya Friend değerinden Privatedaha Protected Friend erişilebilir.

Bir ad alanının bildirim alanı "açık uçlu" olduğundan, aynı tam ada sahip iki ad alanı bildirimi aynı bildirim alanına katkıda bulunur. Aşağıdaki örnekte, iki ad alanı bildirimi aynı bildirim alanına katkıda bulunur, bu durumda tam adlara Data.Customer ve Data.Order:

Namespace Data
    Class Customer
    End Class
End Namespace

Namespace Data
    Class Order
    End Class
End Namespace

İki bildirim aynı bildirim alanına katkıda bulunduğundan, her biri aynı ada sahip bir sınıfın bildirimini içeriyorsa derleme zamanı hatası oluşur.

Aşırı Yükleme ve İmzalar

Bildirim alanında aynı türdeki aynı adlandırılmış varlıkları bildirmenin tek yolu aşırı yükleme yapmaktır. Yalnızca yöntemler, işleçler, örnek oluşturucuları ve özellikler aşırı yüklenebilir.

Aşırı yüklenmiş tür üyeleri benzersiz imzalara sahip olmalıdır. Tür üyesinin imzası, tür parametrelerinin sayısından ve üyenin parametrelerinin sayısından ve türlerinden oluşur. Dönüştürme işleçleri, işlecin dönüş türünü de imzaya ekler.

Aşağıdakiler üyenin imzasının bir parçası değildir ve bu nedenle üzerinde aşırı yüklenemez:

  • Tür üyesine değiştiriciler (örneğin, Shared veya Private).

  • Bir parametrenin değiştiricileri (örneğin, ByVal veya ByRef).

  • Parametrelerin adları.

  • Bir yöntemin veya işlecin dönüş türü (dönüştürme işleçleri hariç) veya bir özelliğin öğe türü.

  • Tür parametresindeki kısıtlamalar.

Aşağıdaki örnekte, imzalarıyla birlikte aşırı yüklenmiş yöntem bildirimleri kümesi gösterilmektedir. Yöntem bildirimlerinden birkaçı aynı imzalara sahip olduğundan bu bildirim geçerli olmayacaktır.

Interface ITest
    Sub F1()                              ' Signature is ().
    Sub F2(x As Integer)                  ' Signature is (Integer).
    Sub F3(ByRef x As Integer)            ' Signature is (Integer).
    Sub F4(x As Integer, y As Integer)    ' Signature is (Integer, Integer).
    Function F5(s As String) As Integer   ' Signature is (String).
    Function F6(x As Integer) As Integer  ' Signature is (Integer).
    Sub F7(a() As String)                 ' Signature is (String()).
    Sub F8(ParamArray a() As String)      ' Signature is (String()).
    Sub F9(Of T)()                        ' Signature is !1().
    Sub F10(Of T, U)(x As T, y As U)      ' Signature is !2(!1, !2)
    Sub F11(Of U, T)(x As T, y As U)      ' Signature is !2(!2, !1)
    Sub F12(Of T)(x As T)                 ' Signature is !1(!1)
    Sub F13(Of T As IDisposable)(x As T)  ' Signature is !1(!1)
End Interface

Sağlanan tür bağımsız değişkenlerine göre aynı imzalara sahip üyeler içerebilecek genel bir tür tanımlamak geçerlidir. Aşırı yükleme çözümleme kuralları, bu tür aşırı yüklemeler arasında ayrım yapmak için kullanılır, ancak kesinleştirmenin imkansız olduğu durumlar olabilir. Örneğin:

Class C(Of T)
    Sub F(x As Integer)
    End Sub

    Sub F(x As T)
    End Sub

    Sub G(Of U)(x As T, y As U)
    End Sub

    Sub G(Of U)(x As U, y As T)
    End Sub
End Class

Module Test
    Sub Main()
        Dim x As New C(Of Integer)
        x.F(10)                   ' Calls C(Of T).F(Integer)
        x.G(Of Integer)(10, 10)    ' Error: Can't choose between overloads
    End Sub
End Module

Scope

Bir varlığın adının kapsamı , niteleme olmadan bu ada başvurmanın mümkün olduğu tüm bildirim alanları kümesidir. Genel olarak, bir varlığın adının kapsamı, bildirim bağlamının tamamıdır; ancak, bir varlığın bildirimi aynı ada sahip varlıkların iç içe bildirimleri içerebilir. Bu durumda iç içe geçmiş varlık dış varlığı gölgeler veya gizler ve gölgeli varlığa erişim yalnızca niteleme yoluyla mümkündür.

İç içe geçme yoluyla gölgeleme, ad alanları içinde iç içe geçmiş ad alanları veya türlerde, diğer türlerin içinde iç içe yerleştirilmiş türlerde ve tür üyelerinin gövdelerinde gerçekleşir. Bildirimlerin iç içe geçme işleminin gölgelenmesi her zaman örtük olarak gerçekleşir; açık söz dizimi gerekmez.

Aşağıdaki örnekte, yönteminin F içinde, örnek değişkeni i yerel değişkeni itarafından gölgelenmiştir, ancak yöntemin Gi içinde yine de örnek değişkenine başvurur.

Class Test
    Private i As Integer = 0

    Sub F()
        Dim i As Integer = 1
    End Sub

    Sub G()
        i = 1
    End Sub
End Class

İç kapsamdaki bir ad dış kapsamdaki bir adı gizlediğinde, bu adın aşırı yüklenmiş tüm oluşumlarını gölgeler. Aşağıdaki örnekte çağrısı, F(1) içinde bildirilen Inner öğesini F çağırır çünkü tüm dış oluşumları F iç bildirim tarafından gizlenir. Aynı nedenle, çağrı F("Hello") hatalıdır.

Class Outer
    Shared Sub F(i As Integer)
    End Sub

    Shared Sub F(s As String)
    End Sub

    Class Inner
        Shared Sub F(l As Long)
        End Sub

        Sub G()
            F(1) ' Invokes Outer.Inner.F.
            F("Hello") ' Error.
        End Sub
    End Class
End Class

Inheritance

Devralma ilişkisi, türetilen türün bildirim alanı örtük olarak erişilebilir oluşturucu olmayan tür üyelerini ve temel türünün iç içe türlerini içerecek şekilde bir türün (türetilmiş tür) başka bir türden (temel tür) türetildiği ilişkidir. Aşağıdaki örnekte, sınıfı A temel sınıfıdır Bve B öğesinden Atüretilmiştir.

Class A
End Class

Class B
    Inherits A
End Class

A Açıkça bir temel sınıf belirtmediğinden, temel sınıfı örtük olarak Objectolur.

Devralma işleminin önemli yönleri şunlardır:

  • Devralma geçişli. C türü B türünden türetilirse ve B türü A türünden türetilirse, C türü B türünde bildirilen tür üyelerini ve A türünde bildirilen tür üyelerini devralır.

  • Türetilmiş bir tür, temel türünü genişletir ancak daraltamaz. Türetilmiş bir tür yeni tür üyeleri ekleyebilir ve devralınan tür üyelerini gölgeleyebilir, ancak devralınan tür üyesinin tanımını kaldıramaz.

  • Bir türün örneği, temel türünün tüm tür üyelerini içerdiğinden, türetilmiş bir türden temel türüne dönüştürme her zaman vardır.

  • türü dışında tüm türlerin bir temel türü Objectolmalıdır. Bu nedenle, Object tüm türlerin nihai temel türüdür ve tüm türler buna dönüştürülebilir.

  • Türetmede döngüselliğe izin verilmez. Yani, bir tür B türünden Atüretildiğinde, türünden A doğrudan veya dolaylı olarak Btüretilen bir hatadır.

  • Bir tür, doğrudan veya dolaylı olarak içinde iç içe yerleştirilmiş bir türden türetilmeyebilir.

Aşağıdaki örnek, sınıflar döngüsel olarak birbirine bağlı olduğundan derleme zamanı hatası oluşturur.

Class A
    Inherits B
End Class

Class B
    Inherits C
End Class

Class C
    Inherits A
End Class

Aşağıdaki örnek, dolaylı olarak sınıfı aracılığıyla Aiç içe geçmiş sınıfından C türetildiği için B bir derleme zamanı hatası da oluşturur.

Class A
    Inherits B.C
End Class

Class B
    Inherits A

    Public Class C
    End Class 
End Class

Sonraki örnek, sınıfından ABtüretilmediğinden hata üretmez.

Class A
    Class B
        Inherits A
    End Class 
End Class

MustInherit ve NotInheritable Sınıfları

Sınıf MustInherit , yalnızca temel tür olarak davranabilen tamamlanmamış bir türdür. Bir MustInherit sınıf örneği oluşturulamadığından, işlecinin bir tanesinde New kullanılması bir hatadır. Sınıfların MustInherit değişkenlerini bildirmek geçerlidir; bu tür değişkenler yalnızca atanabilir Nothing veya sınıfından türetilen bir sınıftan MustInherit gelen bir değer olabilir.

Normal bir sınıf bir MustInherit sınıftan türetildiğinde, normal sınıfın devralınan MustOverride tüm üyeleri geçersiz kılmalıdır. Örneğin:

MustInherit Class A
    Public MustOverride Sub F()
End Class

MustInherit Class B
    Inherits A

    Public Sub G()
    End Sub
End Class 

Class C
    Inherits B

    Public Overrides Sub F()
    End Sub 
End Class

MustInherit sınıfı A bir MustOverride yöntemi Ftanıtır. Sınıfı B ek bir yöntemi Gtanıtır, ancak uygulamasını Fsağlamaz. Bu nedenle sınıfı B da bildirilmelidir MustInherit. Sınıf C geçersiz kılar F ve gerçek bir uygulama sağlar. sınıfında Cbekleyen MustOverride üye olmadığından olması gerekmezMustInherit.

Sınıf NotInheritable , başka bir sınıfın türetilemediği bir sınıftır. NotInheritable sınıflar öncelikli olarak istenmeyen türetme önlemek için kullanılır.

Bu örnekte sınıfından B türetmeye çalıştığından NotInheritable sınıfı Ahatalıdır. Bir sınıf hem hem de MustInheritNotInheritableolarak işaretlenemez.

NotInheritable Class A
End Class

Class B
    ' Error, a class cannot derive from a NotInheritable class.
    Inherits A
End Class

Arabirimler ve Birden Çok Devralma

Yalnızca tek bir temel türden türetilen diğer türlerden farklı olarak, bir arabirim birden çok temel arabirimden türetilebilir. Bu nedenle, bir arabirim farklı temel arabirimlerden aynı adlı tür üyesini devralabilir. Böyle bir durumda, çarpma devralınan ad türetilmiş arabirimde kullanılamaz ve türetilmiş arabirim aracılığıyla bu tür üyelerin herhangi birine başvurmak, imzalardan veya aşırı yüklemeden bağımsız olarak derleme zamanı hatasına neden olur. Bunun yerine, çakışan tür üyelerine bir temel arabirim adı üzerinden başvurulmalıdır.

Aşağıdaki örnekte, çarpma devralınan üye Count arabiriminde IListCounterkullanılamadığından ilk iki deyim derleme zamanı hatalarına neden olur:

Interface IList
    Property Count() As Integer
End Interface

Interface ICounter
    Sub Count(i As Integer)
End Interface

Interface IListCounter
    Inherits IList
    Inherits ICounter 
End Interface 

Module Test
    Sub F(x As IListCounter)
        x.Count(1)                  ' Error, Count is not available.
        x.Count = 1                 ' Error, Count is not available.
        CType(x, IList).Count = 1   ' Ok, invokes IList.Count.
        CType(x, ICounter).Count(1) ' Ok, invokes ICounter.Count.
    End Sub 
End Module

Örnekte gösterildiği gibi belirsizlik, uygun temel arabirim türüne geçirilerek x çözümlenir. Bu tür atamaların çalışma zamanı maliyeti yoktur; yalnızca derleme zamanında örneği daha az türetilmiş bir tür olarak görüntülemektir.

Tek bir tür üyesi birden çok yol aracılığıyla aynı temel arabirimden devralındığında, tür üyesi yalnızca bir kez devralınmış gibi kabul edilir. Başka bir deyişle, türetilmiş arabirim, belirli bir temel arabirimden devralınan her tür üyesinin yalnızca bir örneğini içerir. Örneğin:

Interface IBase
    Sub F(i As Integer)
End Interface

Interface ILeft
    Inherits IBase
End Interface

Interface IRight
    Inherits IBase
End Interface

Interface IDerived
    Inherits ILeft, IRight
End Interface

Class Derived
    Implements IDerived

    ' Only have to implement F once.
    Sub F(i As Integer) Implements IDerived.F
    End Sub
End Class

Tür üyesi adı, devralma hiyerarşisi aracılığıyla bir yolda gölgeliyse, ad tüm yollarda gölgeli olur. Aşağıdaki örnekte, IBase.F üye üye tarafından ILeft.F gölgelenmiştir, ancak içinde IRightgölgelenmez:

Interface IBase
    Sub F(i As Integer)
End Interface 

Interface ILeft
    Inherits IBase

    Shadows Sub F(i As Integer)
End Interface 

Interface IRight
    Inherits IBase

    Sub G()
End Interface 

Interface IDerived
    Inherits ILeft, IRight 
End Interface 

Class Test
    Sub H(d As IDerived)
        d.F(1)                  ' Invokes ILeft.F.
        CType(d, IBase).F(1)    ' Invokes IBase.F.
        CType(d, ILeft).F(1)    ' Invokes ILeft.F.
        CType(d, IRight).F(1)   ' Invokes IBase.F.
    End Sub 
End Class

Çağrıd.F(1), üzerinden geçen IRighterişim yolunda gölgelenmemiş gibi görünse IBase.F de öğesini seçerILeft.F. öğesinden gölgelere ILeftIBase.FIBase erişim yolu olduğundan, öğesinden IDerivedIDerivedIRightIBaseöğesine erişim yolunda da üye gölgeli durumdadır.

Gölgeleme

Türetilmiş tür, devralınan bir tür üyesinin adını yeniden bildirerek gölgeler. Bir adı gölgelendirmek, bu ada sahip devralınan tür üyelerini kaldırmaz; yalnızca bu ada sahip devralınan tüm tür üyelerini türetilmiş sınıfta kullanılamaz hale getirir. Gölgeleme bildirimi herhangi bir varlık türü olabilir.

Fazla yüklenebilen varlıklar, iki gölgelendirme biçiminden birini seçebilir. Ada göre gölgeleme anahtar sözcüğü kullanılarak Shadows belirtilir. Ada göre gölgeleyen bir varlık, tüm aşırı yüklemeler dahil olmak üzere temel sınıftaki her şeyi bu ada göre gizler. Ada ve imzayaOverloads göre gölgelendirme anahtar sözcüğü kullanılarak belirtilir. Ada ve imzaya göre gölgeleyen bir varlık, varlıkla aynı imzaya sahip her şeyi bu ada göre gizler. Örneğin:

Class Base
    Sub F()
    End Sub

    Sub F(i As Integer)
    End Sub

    Sub G()
    End Sub

    Sub G(i As Integer)
    End Sub
End Class

Class Derived
    Inherits Base

    ' Only hides F(Integer).
    Overloads Sub F(i As Integer)
    End Sub

    ' Hides G() and G(Integer).
    Shadows Sub G(i As Integer)
    End Sub
End Class

Module Test
    Sub Main()
        Dim x As New Derived()

        x.F() ' Calls Base.F().
        x.G() ' Error: Missing parameter.
    End Sub
End Module

Bir yöntemi ad ve imzaya göre bağımsız ParamArray değişkenle gölgelendirmek, tüm olası genişletilmiş imzaları değil, yalnızca tek tek imzayı gizler. Gölgeleme yönteminin imzası, gölgeli yöntemin genişletilmemiş imzası ile eşleşse bile bu doğrudur. Aşağıdaki örnek:

Class Base
    Sub F(ParamArray x() As Integer)
        Console.WriteLine("Base")
    End Sub
End Class

Class Derived 
    Inherits Base

    Overloads Sub F(x() As Integer)
        Console.WriteLine("Derived")
    End Sub
End Class

Module Test
    Sub Main
        Dim d As New Derived()
        d.F(10)
    End Sub
End Module

Base, genişletilmemiş biçimiyle Base.Faynı imzaya sahip olsa Derived.F da yazdırır.

Buna karşılık, bağımsız değişkeni olan bir ParamArray yöntem, tüm olası genişletilmiş imzaları değil, yalnızca aynı imzaya sahip yöntemleri gölgeler. Aşağıdaki örnek:

Class Base
    Sub F(x As Integer)
        Console.WriteLine("Base")
    End Sub
End Class

Class Derived
    Inherits Base

    Overloads Sub F(ParamArray x() As Integer)
        Console.WriteLine("Derived")
    End Sub
End Class

Module Test
    Sub Main()
        Dim d As New Derived()
        d.F(10)
    End Sub
End Module

Baseile aynı imzaya Base.Fsahip genişletilmiş bir forma sahip olsa Derived.F bile yazdırır.

Yöntemin veya özelliğin bildirilip bildirilmediğini ShadowsOverridesbelirtmeyen Shadows veya Overloads varsaymayan Overloads bir gölgeleme yöntemi veya özelliği aksi takdirde. Aşırı yüklenmiş bir varlık kümesinin bir üyesi veya Overloads anahtar sözcüğünü belirtirse, tümünün Shadows bunu belirtmesi gerekir. Shadows ve Overloads anahtar sözcükleri aynı anda belirtilemez. Standart Shadows modülde ne belirtilebilir ne de Overloads belirtilebilir; standart modüldeki üyeler örtük olarak öğesinden devralınan Objectgölge üyelerdir.

Arabirim devralma yoluyla çarpma-devralınan (ve dolayısıyla kullanılamaz) bir tür üyesinin adını gölgelendirmek ve bu nedenle adı türetilen arabirimde kullanılabilir hale getirmek için geçerlidir.

Örneğin:

Interface ILeft
    Sub F()
End Interface

Interface IRight
    Sub F()
End Interface

Interface ILeftRight
    Inherits ILeft, IRight

    Shadows Sub F()
End Interface

Module Test
    Sub G(i As ILeftRight)
        i.F() ' Calls ILeftRight.F.
        CType(i, ILeft).F() ' Calls ILeft.F.
        CType(i, IRight).F() ' Calls IRight.F.
    End Sub
End Module

Yöntemlerin devralınan yöntemleri gölgelendirmesine izin verildiğinden, sınıfın aynı imzaya sahip birkaç Overridable yöntem içermesi mümkündür. Yalnızca en çok türetilen yöntem görünür olduğundan bu bir belirsizlik sorunu sunmaz. Aşağıdaki örnekte ve D sınıfları aynı C imzaya sahip iki Overridable yöntem içerir:

Class A
    Public Overridable Sub F()
        Console.WriteLine("A.F")
    End Sub 
End Class 

Class B
    Inherits A

    Public Overrides Sub F()
        Console.WriteLine("B.F")
    End Sub 
End Class 

Class C
    Inherits B

    Public Shadows Overridable Sub F()
        Console.WriteLine("C.F")
    End Sub 
End Class 

Class D
    Inherits C

    Public Overrides Sub F()
        Console.WriteLine("D.F")
    End Sub 
End Class 

Module Test
    Sub Main()
        Dim d As New D()
        Dim a As A = d
        Dim b As B = d
        Dim c As C = d
        a.F()
        b.F()
        c.F()
        d.F()
    End Sub 
End Module

Burada iki Overridable yöntem vardır: biri sınıfı A tarafından tanıtılan, diğeri de sınıfı Ctarafından tanıtılan yöntem. sınıfı C tarafından sunulan yöntem, sınıfından Adevralınan yöntemi gizler. Bu nedenle, sınıfındaki OverridesD bildirimi, sınıfı Ctarafından tanıtılan yöntemi geçersiz kılar ve sınıfı D tarafından Atanıtılan yöntemi geçersiz kılmak mümkün değildir. Örnek çıkışı oluşturur:

B.F
B.F
D.F
D.F

Gizli yöntemi, gizli olmayan daha az türetilmiş bir tür aracılığıyla sınıfın D bir örneğine erişerek çağırmak Overridable mümkündür.

Çoğu durumda sınıfı kullanılamaz hale getireceğinden, yöntemi MustOverride gölgelendirmek geçerli değildir. Örneğin:

MustInherit Class Base
    Public MustOverride Sub F()
End Class

MustInherit Class Derived
    Inherits Base

    Public Shadows Sub F()
    End Sub
End Class

Class MoreDerived
    Inherits Derived

    ' Error: MustOverride method Base.F is not overridden.
End Class

Bu durumda, sınıfı MoreDerived yöntemini geçersiz kılmak MustOverride için gereklidir, ancak sınıfı Derived gölgelendiğinden Base.FBase.Fbu mümkün değildir. geçerli bir alt öğesini bildirmenin Derivedbir yolu yoktur.

Dış kapsamdaki bir adı gölgelendirmenin aksine, devralınan kapsamdan erişilebilir bir adı gölgelendirmek, aşağıdaki örnekte olduğu gibi bir uyarının bildirilmesine neden olur:

Class Base
    Public Sub F()
    End Sub

    Private Sub G()
    End Sub 
End Class

Class Derived
    Inherits Base

    Public Sub F() ' Warning: shadowing an inherited name.
    End Sub

    Public Sub G() ' No warning, Base.G is not accessible here.
    End Sub
End Class

sınıfında Derived yönteminin F bildirimi, bir uyarının bildirilmesine neden olur. Devralınan bir adı gölgelendirmek özellikle hata değildir, çünkü bu temel sınıfların ayrı evrimini ortadan kaldırır. Örneğin, sınıfın daha sonraki bir sürümünde sınıfının Base önceki bir sürümünde mevcut olmayan bir yöntem F sunulduğundan yukarıdaki durum ortaya çıkabilirdi. Yukarıdaki durum bir hata olsaydı, ayrı bir sürüme sahip sınıf kitaplığındaki bir temel sınıfta yapılan herhangi bir değişiklik türetilmiş sınıfların geçersiz olmasına neden olabilir.

Devralınan bir adı gölgelendirmenin neden olduğu uyarı, veya Overloads değiştiricisi Shadows kullanımıyla ortadan kaldırılabilir:

Class Base
    Public Sub F()
    End Sub 
End Class 

Class Derived
    Inherits Base

    Public Shadows Sub F() 'OK.
    End Sub
End Class

Değiştirici, Shadows devralınan üyeyi gölgelendirme amacını gösterir. Gölgelendirmek için bir tür üye adı yoksa veya Overloads değiştiricisini belirtmek Shadows bir hata değildir.

Yeni üye bildirimi, devralınan bir üyeyi aşağıdaki örnekte olduğu gibi yalnızca yeni üyenin kapsamında gölgeler:

Class Base
    Public Shared Sub F()
    End Sub 
End Class 

Class Derived
    Inherits Base

    Private Shared Shadows Sub F() ' Shadows Base.F in class Derived only.
    End Sub 
End Class 

Class MoreDerived
    Inherits Derived

    Shared Sub G()
        F() ' Invokes Base.F.
    End Sub 
End Class

Yukarıdaki örnekte, sınıfında yöntemi F bildirimi sınıfından Basedevralınan yöntemi F gölgeler, ancak sınıfındaki Derived yeni yöntemin F erişimi olduğundan Private kapsamı sınıfına MoreDerivedgenişletilmez.Derived Bu nedenle, F() içinde MoreDerived.G çağrısı geçerlidir ve Base.F'yi çağırır. Aşırı yüklenmiş tür üyeleri söz konusu olduğunda, aşırı yüklenmiş tür üyeleri kümesinin tamamı, gölgeleme amacıyla en uygun erişime sahipmiş gibi kabul edilir.

Class Base
    Public Sub F()
    End Sub
End Class

Class Derived
    Inherits Base

    Private Shadows Sub F()
    End Sub

    Public Shadows Sub F(i As Integer)
    End Sub
End Class

Class MoreDerived
    Inherits Derived

    Public Sub G()
        F()   ' Error. No accessible member with this signature.
    End Sub
End Class

Bu örnekte, içinde Derived bildirimi F() erişimle Private bildirilmiş olsa da, aşırı yüklenmiş F(Integer) erişimle Public bildirilir. Bu nedenle, gölgelendirme amacıyla, içindeki adı F olduğu gibi Publicdeğerlendirilir, bu nedenle her iki yöntem de içinde Basegölge FDerived alır.

Uygulama

Bir tür bir arabirim uyguladığını bildirdiğinde ve tür arabirimin tüm tür üyelerini uyguladığında bir uygulama ilişkisi vardır. Belirli bir arabirimi uygulayan bir tür, bu arabirime dönüştürülebilir. Arabirimlerin örneği oluşturulamaz, ancak arabirim değişkenlerini bildirmek geçerli olur; bu tür değişkenlere yalnızca arabirimini uygulayan bir sınıfın değeri atanabilir. Örneğin:

Interface ITestable
    Function Test(value As Byte) As Boolean
End Interface

Class TestableClass
    Implements ITestable

    Function Test(value As Byte) As Boolean Implements ITestable.Test
        Return value > 128
    End Function
End Class

Module Test
    Sub F()
        Dim x As ITestable = New TestableClass
        Dim b As Boolean

        b = x.Test(34)
    End Sub
End Module

Çarpma devralınan tür üyelerine sahip bir arabirim uygulayan bir tür, uygulanmakta olan türetilmiş arabirimden doğrudan erişilemese bile bu yöntemleri uygulamaya devam etmelidir. Örneğin:

Interface ILeft
    Sub Test()
End Interface

Interface IRight
    Sub Test()
End Interface

Interface ILeftRight
    Inherits ILeft, IRight
End Interface

Class LeftRight
    Implements ILeftRight

    ' Has to reference ILeft explicitly.
    Sub TestLeft() Implements ILeft.Test
    End Sub

    ' Has to reference IRight explicitly.
    Sub TestRight() Implements IRight.Test
    End Sub

    ' Error: Test is not available in ILeftRight.
    Sub TestLeftRight() Implements ILeftRight.Test
    End Sub
End Class

Sınıflar bile MustInherit uygulanan arabirimlerin tüm üyelerinin uygulamalarını sağlamalıdır; ancak, bunları olarak MustOverridebildirerek bu yöntemlerin uygulanmasını erteleyebilirler. Örneğin:

Interface ITest
    Sub Test1()
    Sub Test2()
End Interface

MustInherit Class TestBase
    Implements ITest

    ' Provides an implementation.
    Sub Test1() Implements ITest.Test1
    End Sub

    ' Defers implementation.
    MustOverride Sub Test2() Implements ITest.Test2
End Class

Class TestDerived
    Inherits TestBase

    ' Have to implement MustOverride method.
    Overrides Sub Test2()
    End Sub
End Class

Bir tür, temel türünün uyguladığı bir arabirimi yeniden uygulamayı seçebilir. Arabirimi yeniden uygulamak için türün arabirimi uyguladığını açıkça belirtmesi gerekir. Bir arabirimi yeniden uygulayan bir tür, arabirimin üyelerinin yalnızca bazılarını yeniden uygulamayı seçebilir, ancak tümünü değil-- yeniden uygulanmayan tüm üyeler temel türün uygulamasını kullanmaya devam edebilir. Örneğin:

Class TestBase
    Implements ITest

    Sub Test1() Implements ITest.Test1
        Console.WriteLine("TestBase.Test1")
    End Sub

    Sub Test2() Implements ITest.Test2
        Console.WriteLine("TestBase.Test2")
    End Sub
End Class

Class TestDerived
    Inherits TestBase
    Implements ITest  ' Required to re-implement

    Sub DerivedTest1() Implements ITest.Test1
        Console.WriteLine("TestDerived.DerivedTest1")
    End Sub
End Class

Module Test
    Sub Main()
        Dim Test As ITest = New TestDerived()
        Test.Test1()
        Test.Test2()
    End Sub
End Module

Bu örnek şunu yazdırır:

TestDerived.DerivedTest1
TestBase.Test2

Türetilmiş bir tür, temel arabirimleri türetilmiş türün temel türleri tarafından uygulanan bir arabirim uyguladığında, türetilen tür yalnızca temel türler tarafından henüz uygulanmamış olan arabirimin tür üyelerini uygulamayı seçebilir. Örneğin:

Interface IBase
    Sub Base()
End Interface

Interface IDerived
    Inherits IBase

    Sub Derived()
End Interface

Class Base
    Implements IBase

    Public Sub Base() Implements IBase.Base
    End Sub
End Class

Class Derived
    Inherits Base
    Implements IDerived

    ' Required: IDerived.Derived not implemented by Base.
    Public Sub Derived() Implements IDerived.Derived
    End Sub
End Class

Arabirim yöntemi, temel türdeki geçersiz kılınabilir bir yöntem kullanılarak da uygulanabilir. Bu durumda, türetilmiş bir tür de geçersiz kılınabilir yöntemini geçersiz kılabilir ve arabirimin uygulamasını değiştirebilir. Örneğin:

Class Base
    Implements ITest

    Public Sub Test1() Implements ITest.Test1
        Console.WriteLine("TestBase.Test1")
    End Sub

    Public Overridable Sub Test2() Implements ITest.Test2
        Console.WriteLine("TestBase.Test2")
    End Sub
End Class

Class Derived
    Inherits Base

    ' Overrides base implementation.
    Public Overrides Sub Test2()
        Console.WriteLine("TestDerived.Test2")
    End Sub
End Class

Yöntemleri Uygulama

Bir tür, bir yan tümcesi ile bir yöntem sağlayarak uygulanan arabirimin tür üyesini Implementsuygular. İki tür üyesi aynı sayıda parametreye sahip olmalıdır, isteğe bağlı parametrelerin varsayılan değeri de dahil olmak üzere parametrelerin tüm türleri ve değiştiricileri eşleşmelidir, dönüş türü eşleşmelidir ve yöntem parametrelerindeki kısıtlamaların tümü eşleşmelidir. Örneğin:

Interface ITest
    Sub F(ByRef x As Integer)
    Sub G(Optional y As Integer = 20)
    Sub H(Paramarray z() As Integer)
End Interface

Class Test
    Implements ITest

    ' Error: ByRef/ByVal mismatch.
    Sub F(x As Integer) Implements ITest.F
    End Sub

    ' Error: Defaults do not match.
    Sub G(Optional y As Integer = 10) Implements ITest.G
    End Sub

    ' Error: Paramarray does not match.
    Sub H(z() As Integer) Implements ITest.H
    End Sub
End Class

Tek bir yöntem, tümü yukarıdaki ölçütleri karşılıyorsa herhangi bir sayıda arabirim türü üyesi uygulayabilir. Örneğin:

Interface ITest
    Sub F(i As Integer)
    Sub G(i As Integer)
End Interface

Class Test

    Implements ITest

    Sub F(i As Integer) Implements ITest.F, ITest.G
    End Sub
End Class

Bir yöntemi genel arabirimde uygularken, uygulayan yöntemin arabirimin tür parametrelerine karşılık gelen tür bağımsız değişkenlerini sağlaması gerekir. Örneğin:

Interface I1(Of U, V) 
    Sub M(x As U, y As List(Of V)) 
End Interface

Class C1(Of W, X)
    Implements I1(Of W, X)

    ' W corresponds to U and X corresponds to V
    Public Sub M(x As W, y As List(Of X)) Implements I1(Of W, X).M
    End Sub 
End Class

Class C2
    Implements I1(Of String, Integer)

    ' String corresponds to U and Integer corresponds to V
    Public Sub M(x As String, y As List(Of Integer)) _
        Implements I1(Of String, Integer).M
    End Sub
End Class

Genel bir arabirimin bazı tür bağımsız değişkenleri için uygulanamayabilir.

Interface I1(Of T, U)
    Sub S1(x As T)
    Sub S1(y As U)
End Interface

Class C1
    ' Unable to implement because I1.S1 has two identical signatures
    Implements I1(Of Integer, Integer)
End Class

Çok biçimlilik

Polimorfizm , bir yöntemin veya özelliğin uygulanmasını değiştirebilme olanağı sağlar. Polimorfizm ile aynı yöntem veya özellik, onu çağıran örneğin çalışma zamanı türüne bağlı olarak farklı eylemler gerçekleştirebilir. Polimorfik yöntemler veya özellikler geçersiz kılınabilir olarak adlandırılır. Buna karşılık, geçersiz kılınamaz bir yöntem veya özelliğin uygulanması sabittir; yöntemi veya özelliği, bildirildiği sınıfın bir örneğinde veya türetilmiş bir sınıfın örneğinde çağrılırsa, uygulama aynıdır. Geçersiz kılınamaz bir yöntem veya özellik çağrıldığında, örneğin derleme zamanı türü belirleyici faktördür. Örneğin:

Class Base
    Public Overridable Property X() As Integer
        Get
        End Get

        Set
        End Set
    End Property
End Class

Class Derived
    Inherits Base

    Public Overrides Property X() As Integer
        Get
        End Get

        Set
        End Set
    End Property
End Class

Module Test
    Sub F()
        Dim Z As Base

        Z = New Base()
        Z.X = 10            ' Calls Base.X
        Z = New Derived()
        Z.X = 10            ' Calls Derived.X
    End Sub
End Module

Geçersiz kılınabilir bir yöntem de olabilir MustOverride. Bu, yöntem gövdesi sağlamadığı ve geçersiz kılınması gerektiği anlamına gelir. MustOverride yöntemlerine yalnızca sınıflarda MustInherit izin verilir.

Aşağıdaki örnekte sınıfı Shape , kendisini boyayabilen geometrik şekil nesnesinin soyut tanımını tanımlar:

MustInherit Public Class Shape
    Public MustOverride Sub Paint(g As Graphics, r As Rectangle)
End Class 

Public Class Ellipse
    Inherits Shape

    Public Overrides Sub Paint(g As Graphics, r As Rectangle)
        g.drawEllipse(r)
    End Sub 
End Class 

Public Class Box
    Inherits Shape

    Public Overrides Sub Paint(g As Graphics, r As Rectangle)
        g.drawRect(r)
    End Sub 
End Class

yönteminin PaintMustOverride nedeni, anlamlı bir varsayılan uygulama olmamasıdır. Ellipse ve Box sınıfları somut Shape uygulamalardır. Bu sınıflar olmadığından MustInherit, yöntemini geçersiz kılmak Paint ve gerçek bir uygulama sağlamak için gereklidir.

Aşağıdaki örnekte gösterildiği gibi, temel erişimin bir MustOverride yönteme başvurması hatadır:

MustInherit Class A
    Public MustOverride Sub F()
End Class

Class B
    Inherits A

    Public Overrides Sub F()
        MyBase.F() ' Error, MyBase.F is MustOverride.
    End Sub 
End Class

Bir yönteme MyBase.F() başvuracağından çağrı için bir MustOverride hata bildirilir.

Yöntemleri Geçersiz Kılma

Bir tür, aynı ada ve , imzaya sahip bir yöntem bildirerek ve bildirimi değiştiriciyle işaretleyerek devralınan Overrides geçersiz kılınabilir bir yöntemi geçersiz kılabilir. Yöntemleri geçersiz kılmayla ilgili ek gereksinimler aşağıda listelenmiştir. Yöntem Overridable bildirimi yeni bir yöntem tanıtırken, Overrides yöntem bildirimi yöntemin devralınan uygulamasının yerini alır.

Geçersiz kılma yöntemi, türetilmiş türlerde yöntemin daha fazla geçersiz kılınmasını engelleyen olarak bildirilebilir NotOverridable. Aslında, NotOverridable yöntemler başka türetilmiş sınıflarda geçersiz kılınamaz hale gelir.

Aşağıdaki örneği göz önünde bulundurun:

Class A
    Public Overridable Sub F()
        Console.WriteLine("A.F")
    End Sub

    Public Overridable Sub G()
        Console.WriteLine("A.G")
    End Sub
End Class

Class B
    Inherits A

    Public Overrides NotOverridable Sub F()
        Console.WriteLine("B.F")
    End Sub

    Public Overrides Sub G()
        Console.WriteLine("B.G")
    End Sub
End Class

Class C
    Inherits B

    Public Overrides Sub G()
        Console.WriteLine("C.G")
    End Sub
End Class

Örnekte, sınıfı B iki Overrides yöntem sağlar: değiştiricisi NotOverridable olan bir yöntem F ve olmayan bir yöntemG. Değiştiricinin NotOverridable kullanılması, sınıfının C yöntemini Fgeçersiz kılmasını engeller.

Geçersiz kılma yöntemi, geçersiz kılma yöntemi bildirilmemiş MustOverrideolsa bile olarak da bildirilebilir MustOverride. Bu, içeren sınıfın bildirilmesi MustInherit ve bildirilmeyen MustInherit diğer türetilmiş sınıfların yöntemini geçersiz kılması gerekir. Örneğin:

Class A
    Public Overridable Sub F()
        Console.WriteLine("A.F")
    End Sub
End Class

MustInherit Class B
    Inherits A

    Public Overrides MustOverride Sub F()
End Class

Örnekte, sınıf B bir MustOverride yöntemle geçersiz kılarA.F. Bu, türetilen B tüm sınıfların da bildirilmediği MustInherit sürece öğesini geçersiz kılması Fgerekeceği anlamına gelir.

Geçersiz kılma yöntemi için aşağıdakilerin tümü doğru değilse derleme zamanı hatası oluşur:

  • Bildirim bağlamı, geçersiz kılma yöntemiyle aynı imzaya ve dönüş türüne (varsa) sahip tek bir erişilebilir devralınan yöntem içerir.
  • Geçersiz kılınan devralınan yöntem geçersiz kılınabilir. Başka bir deyişle, geçersiz kılınan devralınan yöntem veya NotOverridabledeğildirShared.
  • Bildirilmekte olan yöntemin erişilebilirlik etki alanı, devralınan yöntemin geçersiz kılınan erişilebilirlik etki alanıyla aynıdır. Bir özel durum vardır: Protected Friend Diğer yöntem geçersiz kılma yönteminin erişimi olmayan Friend başka bir Protected derlemedeyse yöntemin bir yöntem tarafından geçersiz kılınması gerekir.
  • Geçersiz kılma yönteminin parametreleri, isteğe bağlı parametreler için sağlanan değerler de dahil olmak üzere , ByRefParamArray, ve Optional değiştiricilerinin ByValkullanımıyla ilgili olarak geçersiz kılınan yöntemin parametreleriyle eşleşmektedir.
  • Geçersiz kılma yönteminin tür parametreleri, tür kısıtlamaları açısından geçersiz kılınan yöntemin tür parametreleriyle eşleşmektedir.

Temel genel türdeki bir yöntemi geçersiz kılma sırasında geçersiz kılma yöntemi, temel tür parametrelerine karşılık gelen tür bağımsız değişkenlerini sağlamalıdır. Örneğin:

Class Base(Of U, V) 
    Public Overridable Sub M(x As U, y As List(Of V)) 
    End Sub
End Class

Class Derived(Of W, X)
    Inherits Base(Of W, X)

    ' W corresponds to U and X corresponds to V
    Public Overrides Sub M(x As W, y As List(Of X)) 
    End Sub 
End Class

Class MoreDerived
    Inherits Derived(Of String, Integer)

    ' String corresponds to U and Integer corresponds to V
    Public Overrides Sub M(x As String, y As List(Of Integer))
    End Sub
End Class

Genel bir sınıfta geçersiz kılınabilir bir yöntemin bazı tür bağımsız değişken kümeleri için geçersiz kılınamayabileceğini unutmayın. yöntemi bildirilirse MustOverride, bu bazı devralma zincirlerinin mümkün olmayabileceği anlamına gelir. Örneğin:

MustInherit Class Base(Of T, U)
    Public MustOverride Sub S1(x As T)
    Public MustOverride Sub S1(y As U)
End Class

Class Derived
    Inherits Base(Of Integer, Integer)

    ' Error: Can't override both S1's at once
    Public Overrides Sub S1(x As Integer)
    End Sub
End Class

Geçersiz kılma bildirimi, aşağıdaki örnekte olduğu gibi temel erişim kullanarak geçersiz kılınan temel yönteme erişebilir:

Class Base
    Private x As Integer

    Public Overridable Sub PrintVariables()
        Console.WriteLine("x = " & x)
    End Sub
End Class

Class Derived
    Inherits Base

    Private y As Integer

    Public Overrides Sub PrintVariables()
        MyBase.PrintVariables()
        Console.WriteLine("y = " & y)
    End Sub
End Class

Örnekte, sınıfında çağrısıMyBase.PrintVariables(), sınıfında Derived bildirilen Baseyöntemini çağırırPrintVariables. Temel erişim, geçersiz kılınabilir çağırma mekanizmasını devre dışı bırakır ve temel yöntemi geçersiz kılınamaz bir yöntem olarak ele alır. çağrısı Derived yazılmış CType(Me, Base).PrintVariables()olsaydı, içinde bildirilen yöntemi değil, içinde Derivedbildirilen Baseyöntemi yinelemeli olarak çağırırdıPrintVariables.

Yalnızca bir Overrides değiştirici içerdiğinde bir yöntem başka bir yöntemi geçersiz kılabilir. Diğer tüm durumlarda, devralınan yöntemle aynı imzaya sahip bir yöntem, aşağıdaki örnekte olduğu gibi devralınan yöntemi gölgeler:

Class Base
    Public Overridable Sub F()
    End Sub
End Class

Class Derived
    Inherits Base

    Public Overridable Sub F() ' Warning, shadowing inherited F().
    End Sub
End Class

Örnekte, sınıfındaki Derived yöntemi F bir Overrides değiştirici içermez ve bu nedenle sınıfında Baseyöntemini F geçersiz kılmaz. Bunun yerine, sınıfındaki Derived yöntemi F sınıfındaki Baseyöntemi gölgeler ve bildirimi bir veya Overloads değiştirici içermediğinden bir Shadows uyarı bildirilir.

Aşağıdaki örnekte, sınıfındaki yöntemiF, sınıfından Derived devralınan Basegeçersiz kılınabilir yöntemi F gölgeler:

Class Base
    Public Overridable Sub F()
    End Sub
End Class

Class Derived
    Inherits Base

    Private Shadows Sub F() ' Shadows Base.F within Derived.
    End Sub
End Class

Class MoreDerived
    Inherits Derived

    Public Overrides Sub F() ' Ok, overrides Base.F.
    End Sub
End Class

sınıfındaki yeni yöntemin F erişimi olduğundanPrivate, kapsamı yalnızca öğesinin sınıf gövdesini Derived içerir ve sınıfına MoreDerivedgenişletilmez.Derived Bu nedenle sınıfında MoreDerived yöntemi F bildiriminin sınıfından Basedevralınan yöntemi F geçersiz kılmasına izin verilir.

Bir Overridable yöntem çağrıldığında, örnek yönteminin en türetilmiş uygulaması, çağrının temel sınıftaki veya türetilmiş sınıftaki yöntemine olmasına bakılmaksızın, örneğin türüne göre çağrılır. Bir yöntemin M sınıfa OverridableR göre en türetilmiş uygulaması aşağıdaki gibi belirlenir:

  • R giriş bildirimini MiçeriyorsaOverridable, bu en türetilmiş uygulamasıdırM.

  • Aksi takdirde, R geçersiz kılma Miçeriyorsa, bu en türetilmiş uygulamasıdır M.

  • Aksi takdirde, en türetilmiş uygulaması M doğrudan temel sınıfıyla Raynıdır.

Erişilebilirlik

Bildirim, bildirmiş olduğu varlığın erişilebilirliğini belirtir. Varlığın erişilebilirliği, varlığın adının kapsamını değiştirmez. Bildirimin erişilebilirlik etki alanı , bildirilen varlığın erişilebilir olduğu tüm bildirim alanları kümesidir.

Beş erişim türü , , ProtectedFriend, Protected Friendve PrivateşeklindedirPublic. Public en izinli erişim türüdür ve diğer dört tür de alt kümeleridir Public. En az izinli erişim türü olur Privateve diğer dört erişim türünün tümü üst kümeleridir Private.

AccessModifier
    : 'Public'
    | 'Protected'
    | 'Friend'
    | 'Private'
    | 'Protected' 'Friend'
    ;

Bildirimin erişim türü, , , ProtectedFriend, Privateveya ve birleşimi olabilecek Publicisteğe bağlı bir erişim değiştirici aracılığıyla ProtectedFriendbelirtilir. Hiçbir erişim değiştirici belirtilmezse, varsayılan erişim türü bildirim bağlamına bağlıdır; izin verilen erişim türleri de bildirim bağlamına bağlıdır.

  • Değiştirici ile bildirilen varlıkların Public erişimi vardır Public . Varlıkların kullanımıyla Public ilgili bir kısıtlama yoktur.

  • Değiştirici ile bildirilen varlıkların Protected erişimi vardır Protected . Protectederişim yalnızca sınıfların üyelerinde (hem normal tür üyeleri hem de iç içe sınıflar) veya standart modüllerin ve yapıların üyelerinde Overridable belirtilebilir (tanım gereği veya System.ValueTypeöğesinden System.Object devralınması gerekir). Protected Üyenin örnek üyesi olmaması veya erişimin türetilmiş sınıfın bir örneği aracılığıyla gerçekleşmesi koşuluyla, üye türetilmiş bir sınıf için erişilebilir. Protected erişim, bir erişim üst kümesi Friend değildir.

  • Değiştirici ile bildirilen varlıkların Friend erişimi vardır Friend . Erişimi olan Friend bir varlığa yalnızca varlık bildirimini veya özniteliği aracılığıyla System.Runtime.CompilerServices.InternalsVisibleToAttribute erişim verilmiş Friend tüm derlemeleri içeren program içinden erişilebilir.

  • Değiştiricilerle Protected Friend bildirilen varlıklar ve Friend erişim birleşimine Protected sahiptir.

  • Değiştirici ile bildirilen varlıkların Private erişimi vardır Private . Bir Private varlık, iç içe yerleştirilmiş varlıklar da dahil olmak üzere yalnızca bildirim bağlamında erişilebilir.

Bildirimdeki erişilebilirlik, bildirim bağlamının erişilebilir olmasına bağlı değildir. Örneğin, erişimle Private bildirilen bir tür, erişimi olan Public bir tür üyesi içerebilir.

Aşağıdaki kod çeşitli erişilebilirlik etki alanlarını gösterir:

Public Class A
    Public Shared X As Integer
    Friend Shared Y As Integer
    Private Shared Z As Integer
End Class

Friend Class B
    Public Shared X As Integer
    Friend Shared Y As Integer
    Private Shared Z As Integer

    Public Class C
        Public Shared X As Integer
        Friend Shared Y As Integer
        Private Shared Z As Integer
    End Class

    Private Class D
        Public Shared X As Integer
        Friend Shared Y As Integer
        Private Shared Z As Integer
    End Class
End Class

Bu örnekteki sınıflar ve üyeler aşağıdaki erişilebilirlik etki alanlarına sahiptir:

  • A ve A.X erişilebilirlik etki alanı sınırsızdır.

  • , , B, , B.XB.Y, B.C, , B.C.Xve B.C.Y erişilebilirlik etki alanıA.Y, içeren programdır.

  • erişilebilirlik etki alanı A.Z : A.

  • , , B.Dve erişilebilirlik etki alanıB.Z, ve B.Ddahil olmak üzere B.C şeklindedirB.B.D.YB.D.X

  • erişilebilirlik etki alanı B.C.Z şeklindedir B.C.

  • erişilebilirlik etki alanı B.D.Z şeklindedir B.D.

Örnekte gösterildiği gibi, bir üyenin erişilebilirlik etki alanı hiçbir zaman içeren türden büyük değildir. Örneğin, tüm X üyeler erişilebilirlik bildirmiş Public olsa da, A.X ancak tüm üyelerin içeren bir türle kısıtlanmış erişilebilirlik etki alanları vardır.

Örnek üyelerine Protected erişim, ilişkili olmayan türlerin birbirlerinin korumalı üyelerine erişim sağlayamaması için türetilmiş türün bir örneği aracılığıyla olmalıdır. Örneğin:

Class User
    Protected Password As String
End Class

Class Employee
    Inherits User
End Class

Class Guest
    Inherits User

    Public Function GetPassword(u As User) As String
        ' Error: protected access has to go through derived type.
        Return U.Password
    End Function
End Class

Yukarıdaki örnekte, sınıfın Guest yalnızca bir örneğiyle Guestnitelenmişse korumalı Password alana erişimi vardır. Bu, yalnızca öğesine dönüştürerek nesnenin Employee alanına erişim Password kazanmasını UserönlerGuest.

Genel türlerde üye erişimi amacıyla Protected bildirim bağlamı tür parametrelerini içerir. Bu, tür bağımsız değişkenlerinden oluşan bir tür kümesine sahip türetilmiş bir türün, türetilmiş bir türün üyelerine Protected farklı tür bağımsız değişkenleriyle erişimi olmadığı anlamına gelir. Örneğin:

Class Base(Of T)
    Protected x As T
End Class

Class Derived(Of T)
    Inherits Base(Of T)

    Public Sub F(y As Derived(Of String))
        ' Error: Derived(Of T) cannot access Derived(Of String)'s 
        '     protected members
        y.x = "a"
    End Sub
End Class

Not. C# dili (ve büyük olasılıkla diğer diller), genel bir türün hangi tür bağımsız değişkenlerin sağlandığından bağımsız olarak üyelere erişmesine Protected izin verir. Bu, üye içeren Protected genel sınıflar tasarlarken göz önünde bulundurulmalıdır.

Kurucu Türler

Bildirimin kurucu türleri , bildirim tarafından başvuruda bulunan türlerdir. Örneğin, bir sabitin türü, bir yöntemin dönüş türü ve bir oluşturucunun parametre türleri tüm bağlı türlerdir. Bir bildirimin bağlı türündeki erişilebilirlik etki alanı, bildirimin erişilebilirlik etki alanıyla veya üst kümesiyle aynı olmalıdır. Örneğin:

Public Class X
    Private Class Y
    End Class

    ' Error: Exposing private class Y outside of X.
    Public Function Z() As Y
    End Function

    ' Valid: Not exposing outside of X.
    Private Function A() As Y
    End Function
End Class

Friend Class B
    Private Class C
    End Class

    ' Error: Exposing private class Y outside of B.
    Public Function D() As C
    End Function
End Class

Tür ve Ad Alanı Adları

Birçok dil yapısı için ad alanı veya türün belirtilmesi gerekir; bunlar ad alanının veya türün adının nitelikli bir biçimi kullanılarak belirtilebilir. Nitelenmiş ad, noktalarla ayrılmış bir dizi tanımlayıcıdan oluşur; bir dönemin sağ tarafındaki tanımlayıcı, dönemin sol tarafındaki tanımlayıcı tarafından belirtilen bildirim alanında çözümlenir.

Ad alanı veya türün tam adı , ad alanlarını ve türleri içeren tüm adları içeren tam addır. Başka bir deyişle, ad alanı veya türün tam adı , N.Tburada T varlığın adı ve N içeren varlığının tam adıdır.

Aşağıdaki örnekte, satır içi açıklamalarda ilişkili tam adlarıyla birlikte çeşitli ad alanı ve tür bildirimleri gösterilmektedir.

Class A            ' A.
End Class

Namespace X        ' X.
    Class B        ' X.B.
        Class C    ' X.B.C.
        End Class
    End Class

    Namespace Y    ' X.Y.
        Class D    ' X.Y.D.
        End Class
    End Namespace 
End Namespace 

Namespace X.Y      ' X.Y.
    Class E        ' X.Y.E.
    End Class
End Namespace

X.Y ad alanının kaynak kodunda iki farklı konumda bildirildiğini, ancak bu iki kısmi bildirimin hem D hem de E sınıfını içeren X.Y adlı tek bir ad alanı oluşturduğunu gözlemleyin.

Bazı durumlarda, nitelenmiş bir ad anahtar sözcüğüyle Globalbaşlayabilir. anahtar sözcüğü, bir bildirimin kapsayan ad alanını gölgelediği durumlarda yararlı olan adsız en dıştaki ad alanını temsil eder. anahtar sözcüğü, Global bu durumda en dıştaki ad alanına "kaçış" sağlar. Örneğin:

Namespace NS1
    Class System
    End Class

    Module Test
        Sub Main()
            ' Error: Class System does not contain Int32
            Dim x As System.Int32


            ' Legal, binds to System in outermost namespace
            Dim y As Global.System.Int32
        End Sub
    End Module
End Namespace

Yukarıdaki örnekte, tanımlayıcı System ad alanına Systemdeğil sınıfına Systembağlandığından ilk yöntem çağrısı geçersizdir. Ad alanına erişmenin System tek yolu, en dıştaki ad alanına kaçmak için kullanmaktır Global . Global bir Imports deyimde veya Namespace bildirimde kullanılamaz.

Diğer diller dildeki anahtar sözcüklerle eşleşen türler ve ad alanları içerebileceğinden, Visual Basic bir dönemi takip ettikleri sürece anahtar sözcükleri nitelenmiş bir adın parçası olarak tanır. Bu şekilde kullanılan anahtar sözcükler tanımlayıcı olarak değerlendirilir. Örneğin, nitelenmiş tanımlayıcı X.Default.Class geçerli bir nitelenmiş tanımlayıcıdır, ancak Default.Class geçerli değildir.

Ad alanları ve türler için Nitelenmiş Ad Çözümlemesi

formun N.R(Of A)nitelenmiş ad alanı veya tür adı verildiğinde, burada R nitelenmiş ad alanında en sağdaki tanımlayıcıdır ve A isteğe bağlı bir tür bağımsız değişken listesidir, aşağıdaki adımlarda nitelenmiş adın başvurduğu ad alanının veya türün nasıl belirleneceği açıklanmaktadır:

  1. nitelenmiş veya nitelenmemiş ad çözümlemesi için kuralları kullanarak sorununu çözün N.

  2. Çözümleme N başarısız olursa veya bir tür parametresine çözümlendiğinde derleme zamanı hatası oluşur.

  3. Aksi takdirde, N'deki bir ad alanının adıyla eşleşiyorsa ve hiçbir tür bağımsız değişkeni sağlanmadıysa R veya R tür bağımsız değişkenleriyle aynı sayıda tür parametresine sahip erişilebilir bir türle N eşleşiyorsa, varsa, nitelenmiş ad alanı veya türe başvurur.

  4. Aksi takdirde, N bir veya daha fazla standart modül içeriyorsa ve R tam olarak bir standart modülde tür bağımsız değişkenleriyle aynı sayıda tür parametresine sahip erişilebilir bir türün adıyla eşleşiyorsa, tam ad bu türe başvurur. Birden R fazla standart modülde, tür bağımsız değişkenleriyle aynı sayıda tür parametresine sahip erişilebilir türlerin adıyla eşleşiyorsa, derleme zamanı hatası oluşur.

  5. Aksi takdirde derleme zamanı hatası oluşur.

Not. Bu çözümleme işleminin bir etkisi, ad alanı veya tür adlarını çözümlerken tür üyelerinin ad alanlarını veya türleri gölgelememesidir.

Ad alanları ve türler için nitelenmemiş Ad Çözümlemesi

İsteğe bağlı tür bağımsız değişken listesi olan A nitelenmemiş bir ad R(Of A)verildiğinde, aşağıdaki adımlarda nitelenmemiş adın hangi ad alanına başvurduğu veya yazacağı açıklanmaktadır:

  1. R geçerli yöntemin tür parametresinin adıyla eşleşiyorsa ve hiçbir tür bağımsız değişkeni sağlanmamışsa, nitelenmemiş ad bu tür parametresine başvurur.

  2. En içteki türden başlayıp en dıştakine giderek ad başvuruyu içeren her iç içe tür için:

    1. Geçerli türdeki tür parametresinin adıyla eşleşiyorsa ve hiçbir tür bağımsız değişkeni sağlanmamışsa R , nitelenmemiş ad bu tür parametresine başvurur.
    2. Aksi takdirde R , varsa, tür bağımsız değişkenleriyle aynı sayıda tür parametresiyle erişilebilir bir iç içe türün adıyla eşleşiyorsa, nitelenmemiş ad bu türe başvurur.
  3. En içteki ad alanından başlayıp en dıştaki ad alanına giderek ad başvurularını içeren her iç içe yerleştirilmiş ad alanı için:

    1. Geçerli ad alanında iç içe bir ad alanının adıyla eşleşiyorsa R ve hiçbir tür bağımsız değişken listesi sağlanmazsa, nitelenmemiş ad alanı bu iç içe ad alanına başvurur.
    2. Aksi takdirde R , geçerli ad alanında varsa, tür bağımsız değişkenleriyle aynı sayıda tür parametresine sahip erişilebilir bir türün adıyla eşleşiyorsa, nitelenmemiş ad bu türe başvurur.
    3. Aksi takdirde, ad alanı bir veya daha fazla erişilebilir standart modül içeriyorsa ve R varsa, tam olarak bir standart modülde tür bağımsız değişkenleriyle aynı sayıda tür parametresiyle erişilebilir bir iç içe türün adıyla eşleşiyorsa, nitelenmemiş ad bu iç içe türü ifade eder. Birden R fazla standart modülde, tür bağımsız değişkenleriyle aynı sayıda tür parametresine sahip erişilebilir iç içe türlerin adıyla eşleşiyorsa, derleme zamanı hatası oluşur.
  4. Kaynak dosyada bir veya daha fazla içeri aktarma diğer adı varsa ve R bunlardan birinin adıyla eşleşiyorsa, nitelenmemiş ad bu içeri aktarma diğer adına başvurur. Tür bağımsız değişkeni listesi sağlanırsa, derleme zamanı hatası oluşur.

  5. Ad başvuruyu içeren kaynak dosyada bir veya daha fazla içeri aktarma varsa:

    1. Tam R olarak bir içeri aktarmada, tür bağımsız değişkenleriyle aynı sayıda tür parametresine sahip erişilebilir bir türün adıyla eşleşiyorsa, nitelenmemiş ad bu türe başvurur. Erişilebilir R bir türün adı, tür bağımsız değişkenleriyle aynı sayıda tür parametresiyle eşleşiyorsa , varsa, birden fazla içeri aktarmada ve tümü aynı türde değilse, derleme zamanı hatası oluşur.
    2. Aksi takdirde, hiçbir tür bağımsız değişken listesi sağlanmamışsa ve R tam olarak bir içeri aktarmada erişilebilir türleri olan bir ad alanının adıyla eşleşiyorsa, nitelenmemiş ad alanı bu ad alanına başvurur. Hiçbir tür bağımsız değişken listesi sağlanmadıysa ve R birden fazla içeri aktarmada erişilebilir türler içeren bir ad alanının adıyla eşleşiyorsa ve hepsi aynı ad alanı değilse, derleme zamanı hatası oluşur.
    3. Aksi takdirde, içeri aktarmalar bir veya daha fazla erişilebilir standart modül içeriyorsa ve R varsa, tam olarak bir standart modülde tür bağımsız değişkenleriyle aynı sayıda tür parametresiyle erişilebilir bir iç içe türün adıyla eşleşiyorsa, nitelenmemiş ad bu türe başvurur. Birden R fazla standart modülde, tür bağımsız değişkenleriyle aynı sayıda tür parametresine sahip erişilebilir iç içe türlerin adıyla eşleşiyorsa, derleme zamanı hatası oluşur.
  6. Derleme ortamı bir veya daha fazla içeri aktarma diğer adını tanımlıyorsa ve R bunlardan birinin adıyla eşleşiyorsa, nitelenmemiş ad bu içeri aktarma diğer adına başvurur. Tür bağımsız değişkeni listesi sağlanırsa, derleme zamanı hatası oluşur.

  7. Derleme ortamı bir veya daha fazla içeri aktarma tanımlıyorsa:

    1. Tam R olarak bir içeri aktarmada, tür bağımsız değişkenleriyle aynı sayıda tür parametresine sahip erişilebilir bir türün adıyla eşleşiyorsa, nitelenmemiş ad bu türe başvurur. Birden R fazla içeri aktarmada, tür bağımsız değişkenleriyle aynı sayıda tür parametresine sahip erişilebilir bir türün adıyla eşleşiyorsa, derleme zamanı hatası oluşur.
    2. Aksi takdirde, hiçbir tür bağımsız değişken listesi sağlanmamışsa ve R tam olarak bir içeri aktarmada erişilebilir türleri olan bir ad alanının adıyla eşleşiyorsa, nitelenmemiş ad alanı bu ad alanına başvurur. Hiçbir tür bağımsız değişken listesi sağlanmadıysa ve R birden fazla içeri aktarmada erişilebilir türleri olan bir ad alanının adıyla eşleşiyorsa, derleme zamanı hatası oluşur.
    3. Aksi takdirde, içeri aktarmalar bir veya daha fazla erişilebilir standart modül içeriyorsa ve R varsa, tam olarak bir standart modülde tür bağımsız değişkenleriyle aynı sayıda tür parametresiyle erişilebilir bir iç içe türün adıyla eşleşiyorsa, nitelenmemiş ad bu türe başvurur. Birden R fazla standart modülde, tür bağımsız değişkenleriyle aynı sayıda tür parametresine sahip erişilebilir iç içe türlerin adıyla eşleşiyorsa, derleme zamanı hatası oluşur.
  8. Aksi takdirde derleme zamanı hatası oluşur.

Not. Bu çözümleme işleminin bir etkisi, ad alanı veya tür adlarını çözümlerken tür üyelerinin ad alanlarını veya türleri gölgelememesidir.

Normalde, bir ad belirli bir ad alanında yalnızca bir kez oluşabilir. Ancak, ad alanları birden çok .NET derlemesi arasında bildirilebildiği için, iki derlemenin aynı tam ada sahip bir tür tanımladığı bir duruma sahip olmak mümkündür. Bu durumda, geçerli kaynak dosya kümesinde bildirilen bir tür, dış .NET derlemesinde bildirilen bir türe göre tercih edilir. Aksi takdirde, ad belirsizdir ve adı kesinleştirmenin bir yolu yoktur.

Değişkenler

Değişken bir depolama konumunu temsil eder. Her değişkenin, değişkende hangi değerlerin depolanabileceğini belirleyen bir türü vardır. Visual Basic tür açısından güvenli bir dil olduğundan, programdaki her değişkenin bir türü vardır ve dil, değişkenlerde depolanan değerlerin her zaman uygun türde olduğunu garanti eder. Değişkenlere herhangi bir başvuru yapılamadan önce değişkenler her zaman türünün varsayılan değerine başlatılır. Başlatılmamış belleğe erişmek mümkün değildir.

Genel Türler ve Yöntemler

Türler (standart modüller ve numaralandırılmış türler dışında) ve yöntemler, türün bir örneği bildirilene veya yöntemi çağrılana kadar sağlanmayan tür parametreleri bildirebilir. Tür veya yöntemin, türü veya yöntemi kullanan kod tarafından sağlanacak türler hakkında belirli bir bilgi olmadan genel olarak yazılması gerektiğinden, tür parametrelerine sahip türler ve yöntemler sırasıyla genel türler ve genel yöntemler olarak da bilinir.

Not. Şu anda yöntemler ve temsilciler genel olsa da özellikler, olaylar ve işleçler genel olamaz. Ancak, içeren sınıftan tür parametrelerini kullanabilirler.

Genel tür veya yöntem açısından bakıldığında tür parametresi, tür veya yöntem kullanıldığında gerçek bir türle doldurulacak yer tutucu bir türdür. Tür bağımsız değişkenleri, türün veya yöntemin kullanıldığı noktada tür veya yöntemdeki tür parametreleriyle değiştirilir. Örneğin, genel bir yığın sınıfı şu şekilde uygulanabilir:

Public Class Stack(Of ItemType)
    Protected Items(0 To 99) As ItemType
    Protected CurrentIndex As Integer = 0

    Public Sub Push(data As ItemType)
        If CurrentIndex = 100 Then
            Throw New ArgumentException("Stack is full.")
        End If

        Items(CurrentIndex) = Data
        CurrentIndex += 1
    End Sub

    Public Function Pop() As ItemType
        If CurrentIndex = 0 Then
            Throw New ArgumentException("Stack is empty.")
        End If

        CurrentIndex -= 1
        Return Items(CurrentIndex + 1) 
    End Function
End Class

sınıfını Stack(Of ItemType) kullanan bildirimler, tür parametresi ItemTypeiçin bir tür bağımsız değişkeni sağlamalıdır. Bu tür daha sonra sınıfın içinde kullanılan her yerde ItemType doldurulur:

Option Strict On

Module Test
    Sub Main()
        Dim s1 As New Stack(Of Integer)()
        Dim s2 As New Stack(Of Double)()

        s1.Push(10.10)   ' Error: Stack(Of Integer).Push takes an Integer
        s2.Push(10.10)   ' OK: Stack(Of Double).Push takes a Double
        Console.WriteLine(s2.Pop().GetType().ToString()) ' Prints: Double
    End Sub
End Module

Tür Parametreleri

Tür parametreleri tür veya yöntem bildirimlerinde sağlanabilir. Her tür parametresi, bir tür bağımsız değişkeninin yer tutucusu olan ve yapılı bir tür veya yöntem oluşturmak için sağlanan bir tanımlayıcıdır. Buna karşılık, tür bağımsız değişkeni, genel bir tür veya yöntem kullanıldığında tür parametresinin yerini alan gerçek türdür.

TypeParameterList
    : OpenParenthesis 'Of' TypeParameter ( Comma TypeParameter )* CloseParenthesis
    ;

TypeParameter
    : VarianceModifier? Identifier TypeParameterConstraints?
    ;

VarianceModifier
    : 'In' | 'Out'
    ;

Tür veya yöntem bildirimindeki her tür parametresi, bu tür veya yöntemin bildirim alanında bir ad tanımlar. Bu nedenle, başka bir tür parametresi, tür üyesi, yöntem parametresi veya yerel değişken ile aynı ada sahip olamaz. Tür veya yöntemdeki tür parametresinin kapsamı, türün veya yöntemin tamamıdır. Tür parametrelerinin kapsamı tür bildiriminin tamamına göre belirlenmiş olduğundan, iç içe türler dış tür parametrelerini kullanabilir. Bu, genel türlerin içinde iç içe yerleştirilmiş türlere erişirken tür parametrelerinin her zaman belirtilmesi gerektiği anlamına da gelir:

Public Class Outer(Of T)
    Public Class Inner
        Public Sub F(x As T)
            ...
        End Sub
    End Class
End Class

Module Test
    Sub Main()
        Dim x As New Outer(Of Integer).Inner()
        ...
    End Sub
End Module

Sınıfın diğer üyelerinden farklı olarak tür parametreleri devralınmıyor. Türdeki tür parametrelerine yalnızca basit adlarıyla başvurulabilir; başka bir deyişle, içeren tür adıyla nitelenemezler. Hatalı programlama stili olsa da, iç içe bir türdeki tür parametreleri dış türde bildirilen bir üyeyi veya tür parametresini gizleyebilir:

Class Outer(Of T)
    Class Inner(Of T)
        Public t1 As T    ' Refers to Inner's T
    End Class
End Class

Türler ve yöntemler, türlerin veya yöntemlerin bildirmiş olduğu tür parametrelerinin (veya arity) sayısına göre aşırı yüklenebilir. Örneğin, aşağıdaki bildirimler yasaldır:

Module C
    Sub M()
    End Sub

    Sub M(Of T)()
    End Sub

    Sub M(Of T, U)()
    End Sub
End Module

Structure C(Of T)
    Dim x As T
End Structure

Class C(Of T, U)
End Class

Türler söz konusu olduğunda, aşırı yüklemeler her zaman belirtilen tür bağımsız değişken sayısıyla eşleştirilir. Bu, aynı programda hem genel hem de genel olmayan sınıfları birlikte kullanırken kullanışlıdır:

Class Queue 
End Class      

Class Queue(Of T)
End Class

Class X
    Dim q1 As Queue                 ' Non-generic queue
    Dim q2 As Queue(Of Integer)     ' Generic queue
End Class

Tür parametrelerinde aşırı yüklenen yöntemlerin kuralları, yöntem aşırı yükleme çözümlemesi bölümünde ele alınmıştır.

içeren bildiriminde tür parametreleri tam türler olarak kabul edilir. Bir tür parametresinin örneği birçok farklı gerçek tür bağımsız değişkeniyle oluşturulabildiğinden, tür parametreleri aşağıda açıklandığı gibi diğer türlerden biraz farklı işlemlere ve kısıtlamalara sahiptir:

  • Tür parametresi doğrudan bir temel sınıf veya arabirim bildirmek için kullanılamaz.

  • Tür parametrelerinde üye arama kuralları, tür parametresine uygulanan kısıtlamalara (varsa) bağlıdır.

  • Tür parametresi için kullanılabilir dönüştürmeler, varsa tür parametrelerine uygulanan kısıtlamalara bağlıdır.

  • Kısıtlama olmadığındaStructure, bir tür parametresiyle temsil edilen türe sahip bir değer ve IsNotile Is karşılaştırılabilirNothing.

  • Tür parametresi yalnızca tür parametresi bir New veya Structure kısıtlaması tarafından New kısıtlanmışsa ifadede kullanılabilir.

  • Tür parametresi, bir ifade içindeki öznitelik özel durumu içinde herhangi bir GetType yerde kullanılamaz.

  • Tür parametreleri, diğer genel türler ve parametreler için tür bağımsız değişkenleri olarak kullanılabilir.

Aşağıdaki örnek, sınıfını genişleten Stack(Of ItemType) genel bir türdür:

Class MyStack(Of ItemType)
    Inherits Stack(Of ItemType)

    Public ReadOnly Property Size() As Integer
        Get
            Return CurrentIndex
        End Get
    End Property
End Class

Bir bildirim için MyStackbir tür bağımsız değişkeni sağladığında, aynı tür bağımsız değişkeni de uygulanır Stack .

Tür olarak, tür parametreleri yalnızca bir derleme zamanı yapısıdır. Çalışma zamanında, her tür parametresi, genel bildirime bir tür bağımsız değişkeni sağlayarak belirtilen bir çalışma zamanı türüne bağlıdır. Bu nedenle, tür parametresiyle bildirilen bir değişkenin türü, çalışma zamanında genel olmayan bir tür veya belirli bir yapılı tür olacaktır. Tür parametreleriyle ilgili tüm deyimlerin ve ifadelerin çalışma zamanı yürütmesi, bu parametre için tür bağımsız değişkeni olarak sağlanan gerçek türü kullanır.

Tür Kısıtlamaları

Tür bağımsız değişkeni tür sistemindeki herhangi bir tür olabileceğinden, genel bir tür veya yöntem tür parametresi hakkında herhangi bir varsayımda bulunamaz. Bu nedenle, bir tür parametresinin üyeleri türünün üyeleri Objectolarak kabul edilir, çünkü tüm türler türünden Objecttüretilir.

gibi Stack(Of ItemType)bir koleksiyon söz konusu olduğunda, bu olgu özellikle önemli bir kısıtlama olmayabilir, ancak genel bir türün tür bağımsız değişkenleri olarak sağlanacak türler hakkında bir varsayımda bulunmak isteyebileceği durumlar olabilir. Tür kısıtlamaları , tür parametresi olarak hangi türlerin sağlanabileceğini kısıtlayan ve genel türlerin veya yöntemlerin tür parametreleri hakkında daha fazla bilgi edinebilmesini sağlayan tür parametrelerine yerleştirilebilir.

TypeParameterConstraints
    : 'As' Constraint
    | 'As' OpenCurlyBrace ConstraintList CloseCurlyBrace
    ;

ConstraintList
    : Constraint ( Comma Constraint )*
    ;

Constraint
    : TypeName
    | 'New'
    | 'Structure'
    | 'Class'
    ;
Public Class DisposableStack(Of ItemType As IDisposable)
    Implements IDisposable

    Private _items(0 To 99) As ItemType
    Private _currentIndex As Integer = 0

    Public Sub Push(data As ItemType)
        ...
    End Sub

    Public Function Pop() As ItemType
        ...
    End Function

    Private Sub Dispose() Implements IDisposable.Dispose
        For Each item As IDisposable In _items
            If item IsNot Nothing Then
                item.Dispose()
            End If
        Next item
    End Sub
End Class

Bu örnekte, DisposableStack(Of ItemType) türü parametresini yalnızca arabirimini System.IDisposableuygulayan türlerle kısıtlar. Sonuç olarak, kuyrukta kalan nesneleri atan bir Dispose yöntem uygulayabilir.

Tür kısıtlaması, Structure, veya özel kısıtlamalarından Classbiri olmalı veya Newaşağıdaki durumlarda bir tür T olmalıdır:

  • T bir sınıf, arabirim veya tür parametresidir.

  • T değil NotInheritable.

  • T şu özel türlerden biri veya türünden devralınmış bir tür değildir: System.Array, System.Delegate, System.MulticastDelegate, System.Enumveya System.ValueType.

  • T değil Object. Tüm türler türünden türetildiğinden Object, izin verildiğinde böyle bir kısıtlamanın hiçbir etkisi olmaz.

  • T en az bildirilen genel tür veya yöntem kadar erişilebilir olmalıdır.

Tür kısıtlamaları küme ayracı ({} ) içine alınarak tek bir tür parametresi için birden çok tür kısıtlaması belirtilebilir. Belirli bir tür parametresi için yalnızca bir tür kısıtlaması sınıf olabilir. Özel bir Structure kısıtlamayı adlandırılmış bir sınıf kısıtlamasıyla veya Class özel kısıtlamayla birleştirmek bir hatadır.

Class ControlFactory(Of T As {Control, New})
    ...
End Class

Tür kısıtlamaları, içeren türleri veya içeren türlerin tür parametrelerinden herhangi birini kullanabilir. Aşağıdaki örnekte kısıtlama, sağlanan tür bağımsız değişkeninin kendisini tür bağımsız değişkeni olarak kullanan genel bir arabirim uygulamasını gerektirir:

Class Sorter(Of V As IComparable(Of V))
    ...
End Class

Özel tür kısıtlaması Class , sağlanan tür bağımsız değişkenini herhangi bir başvuru türüyle kısıtlar.

Not. Özel tür kısıtlaması Class bir arabirim tarafından karşılanabilir. Ve bir yapı bir arabirim uygulayabilir. Bu nedenle, kısıtlama (Of T As U, U As Class) "T" bir yapıdan (özel kısıtlamayı Class karşılamayan) ve uyguladığı bir arabirimden (özel kısıtlamayı Class karşılayan) "U" ile karşılanabilir.

Özel tür kısıtlaması Structure , sağlanan tür bağımsız değişkenini dışındaki System.Nullable(Of T)herhangi bir değer türüyle kısıtlar.

Not. Yapı kısıtlamaları, kendisine tür bağımsız değişkeni olarak sağlamanın System.Nullable(Of T) mümkün olmaması için izin System.Nullable(Of T) vermez.

Özel tür kısıtlaması New , sağlanan tür bağımsız değişkeninin erişilebilir bir parametresiz oluşturucuya sahip olmasını gerektirir ve bildirilemez MustInherit. Örneğin:

Class Factory(Of T As New)
    Function CreateInstance() As T
        Return New T()
    End Function
End Class

Sınıf türü kısıtlaması, sağlanan tür bağımsız değişkeninin bu tür olması veya ondan devralması gerekir. Arabirim türü kısıtlaması, sağlanan tür bağımsız değişkeninin bu arabirimi uygulaması gerekir. Tür parametresi kısıtlaması, sağlanan tür bağımsız değişkeninin eşleşen tür parametresi için verilen tüm sınırları türetmesi veya uygulaması gerekir. Örneğin:

Class List(Of T)
    Sub AddRange(Of S As T)(collection As IEnumerable(Of S))
        ...
    End Sub
End Class

Bu örnekte, üzerindeki AddRange tür parametresiS, türü parametresiyle TListkısıtlanır. Bu, bir List(Of Control) öğesinin tür parametresini olan veya öğesinden Controldevralan herhangi bir türle sınırlandıracağı AddRangeanlamına gelir.

Tür parametresi kısıtlamasıOf S As T, özel kısıtlamalar (Class, Structure, New) dışında tüm Tkısıtlamaları geçişli olarak öğesine Seklenerek çözülür. Döngüsel kısıtlamaların olması bir hatadır (örn. Of S As T, T As S). Kısıtlamaya sahip tür parametresi kısıtlaması Structure olması bir hatadır. Kısıtlamalar eklendikten sonra, bir dizi özel durum oluşabilir:

  • Birden çok sınıf kısıtlaması varsa, en çok türetilmiş sınıf kısıtlama olarak kabul edilir. Bir veya daha fazla sınıf kısıtlamasının devralma ilişkisi yoksa, kısıtlama karşılanamaz ve bir hatadır.

  • Tür parametresi özel bir Structure kısıtlamayı adlandırılmış sınıf kısıtlamasıyla veya özel kısıtlamayla Class birleştirirse, bu bir hatadır. Sınıf kısıtlaması olabilir NotInheritable, bu durumda bu kısıtlamanın türetilmiş türleri kabul edilmez ve bu bir hatadır.

Tür, şu özel türlerden biri veya öğesinden devralınan bir tür olabilir: System.Array, System.Delegate, System.MulticastDelegate, System.Enumveya System.ValueType. Bu durumda, yalnızca türü veya ondan devralınan bir tür kabul edilir. Bu türlerden biriyle kısıtlanmış bir tür parametresi yalnızca işleç tarafından DirectCast izin verilen dönüştürmeleri kullanabilir. Örneğin:

MustInherit Class Base(Of T)
    MustOverride Sub S1(Of U As T)(x As U)
End Class

Class Derived
    Inherits Base(Of Integer)

    ' The constraint of U must be Integer, which is normally not allowed.
    Overrides Sub S1(Of U As Integer)(x As U)
        Dim y As Integer = x    ' OK
        Dim z As Long = x       ' Error: Can't convert
    End Sub
End Class

Ayrıca, yukarıdaki gevşemelerden biri nedeniyle bir değer türüyle kısıtlanmış tür parametresi, bu değer türünde tanımlanan hiçbir yöntemi çağıramaz. Örneğin:

Class C1(Of T)
    Overridable Sub F(Of G As T)(x As G)
    End Sub
End Class

Class C2
    Inherits C1(Of IntPtr)

    Overrides Sub F(Of G As IntPtr)(ByVal x As G)
        ' Error: Cannot access structure members
         x.ToInt32()
    End Sub
End Class

Değiştirmeden sonra kısıtlama bir dizi türü olarak biterse, herhangi bir kovaryan dizi türüne de izin verilir. Örneğin:

Module Test
    Class B
    End Class

    Class D
        Inherits B
    End Class

    Function F(Of T, U As T)(x As U) As T
        Return x
    End Function

    Sub Main()
        Dim a(9) As B
        Dim b(9) As D

        a = F(Of B(), D())(b)
    End Sub
End Module

Sınıf veya arabirim kısıtlamasına sahip bir tür parametresinin, bu sınıf veya arabirim kısıtlamasıyla aynı üyelere sahip olduğu kabul edilir. Tür parametresinin birden çok kısıtlaması varsa, tür parametresinin kısıtlamaların tüm üyelerinin birleşimine sahip olduğu kabul edilir. Birden fazla kısıtlamada aynı ada sahip üyeler varsa, üyeler şu sırayla gizlenir: sınıf kısıtlaması, içindeki üyeleri gizleyen (kısıtlama belirtilmişseStructure) arabirim kısıtlamalarındaki System.ValueTypeObjectüyeleri gizler ve içindeki üyeleri gizler. Aynı ada sahip bir üye birden fazla arabirim kısıtlamasında görünüyorsa üye kullanılamaz (birden çok arabirim devralmada olduğu gibi) ve tür parametresi istenen arabirime atanmalıdır. Örneğin:

Class C1
    Sub S1(x As Integer)
    End Sub
End Class

Interface I1
    Sub S1(x As Integer)
End Interface

Interface I2
    Sub S1(y As Double)
End Interface

Module Test
    Sub T1(Of T As {C1, I1, I2})()
        Dim a As T
        a.S1(10)       ' Calls C1.S1, which is preferred
        a.S1(10.10)    ' Also calls C1.S1, class is still preferred
    End Sub

    Sub T2(Of T As {I1, I2})()
        Dim a As T
        a.S1(10)    ' Error: Call is ambiguous between I1.S1, I2.S1
    End Sub
End Module

Tür parametrelerini tür bağımsız değişkenleri olarak sağlarken, tür parametrelerinin eşleşen tür parametrelerinin kısıtlamalarını karşılaması gerekir.

Class Base(Of T As Class)
End Class

Class Derived(Of V)
    ' Error: V does not satisfy the constraints of T
    Inherits Base(Of V)
End Class

Kısıtlamada belirtilen örnek yöntemleri de dahil olmak üzere örnek üyelerine erişmek için kısıtlanmış tür parametresinin değerleri kullanılabilir.

Interface IPrintable
    Sub Print()
End Interface

Class Printer(Of V As IPrintable)
    Sub PrintOne(v1 As V)
        V1.Print()
    End Sub
End Class

Tür Parametresi Varyansı

Arabirimdeki veya temsilci türü bildirimindeki tür parametresi isteğe bağlı olarak bir varyans değiştirici belirtebilir. Varyans değiştiricileri olan tür parametreleri, tür parametresinin arabirimde veya temsilci türünde nasıl kullanılabileceğini kısıtlar, ancak genel bir arabirimin veya temsilci türünün değişken uyumlu tür bağımsız değişkenleriyle başka bir genel türe dönüştürülmesini sağlar. Örneğin:

Class Base
End Class

Class Derived
    Inherits Base
End Class

Module Test
    Sub Main()
        Dim x As IEnumerable(Of Derived) = ...

        ' OK, as IEnumerable(Of Base) is variant compatible
        ' with IEnumerable(Of Derived)
        Dim y As IEnumerable(Of Base) = x
    End Sub
End Module

Varyans değiştiricileri olan tür parametrelerine sahip genel arabirimlerin çeşitli kısıtlamaları vardır:

  • Parametre listesini belirten bir olay bildirimi içeremezler (ancak özel olay bildirimine veya temsilci türüne sahip bir olay bildirimine izin verilir).

  • İç içe geçmiş bir sınıf, yapı veya numaralandırılmış tür içeremezler.

Not. Bu kısıtlamalar, genel türlerde iç içe yerleştirilmiş türlerin üstlerinin genel parametrelerini örtük olarak kopyalamalarından kaynaklanır. İç içe geçmiş sınıflar, yapılar veya numaralandırılmış türler söz konusu olduğunda, bu tür türlerin tür parametrelerinde varyans değiştiricileri olamaz. Parametre listesi içeren bir olay bildirimi söz konusu olduğunda, oluşturulan iç içe temsilci sınıfı, bir konumda (parametre türü gibi) gerçekten bir konumda (örneğin olayın türü) kullanılıyor gibi görünen bir InOut tür kullanıldığında kafa karıştırıcı hatalar olabilir.

Out değiştiricisi ile bildirilen tür parametresi birlikte değişkendir. Gayri resmi olarak, bir kovarant türü parametresi yalnızca bir çıkış konumunda (arabirimden veya temsilci türünden döndürülen bir değer) kullanılabilir ve giriş konumunda kullanılamaz. Aşağıdakiler durumunda bir türün Taynı anda geçerli olduğu kabul edilir:

  • T bir sınıf, yapı veya numaralandırılmış türdür.

  • T genel olmayan temsilci veya arabirim türüdür.

  • T , öğe türü aynı anda geçerli olan bir dizi türüdür.

  • T tür parametresi olarak bildirilmemiş bir Out tür parametresidir.

  • T, aşağıdaki gibi tür bağımsız değişkenleriyle A1,...,An oluşturulan bir arabirim veya temsilci türüdürX(Of P1,...,Pn):

    • Out türü parametresi Ai olarak bildirildiysePi, aynı anda geçerli olur.

    • In türü parametresi Ai olarak bildirildiysePi, ters değişken olarak geçerli olur.

Aşağıdakiler bir arabirimde veya temsilci türünde birlikte geçerli olmalıdır:

  • Bir arabirimin temel arabirimi.

  • bir işlevin veya temsilci türünün dönüş türü.

  • Erişimci varsa özelliğin Get türü.

  • Herhangi bir ByRef parametrenin türü.

Örneğin:

Delegate Function D(Of Out T, U)(x As U) As T

Interface I1(Of Out T)
End Interface

Interface I2(Of Out T)
    Inherits I1(Of T)

    ' OK, T is only used in an Out position
    Function M1(x As I1(Of T)) As T

    ' Error: T is used in an In position
    Function M2(x As T) As T
End Interface

Not. Out ayrılmış bir sözcük değildir.

In değiştiricisi ile bildirilen tür parametresi değişkensizdir. Kayıt dışı olarak, değişken karşıtı bir tür parametresi yalnızca giriş konumunda (arabirime veya temsilci türüne geçirilen bir değer) kullanılabilir ve çıkış konumunda kullanılamaz. Bir türün T aşağıdakiler için geçerli olduğu kabul edilir:

  • T bir sınıf, yapı veya numaralandırılmış türdür.

  • T genel olmayan bir temsilci veya arabirim türüdür.

  • T , öğe türü ters değişken olarak geçerli olan bir dizi türüdür.

  • T , In türü parametresi olarak bildirilmemiş bir tür parametresidir.

  • T, aşağıdaki gibi tür bağımsız değişkenleriyle A1,...,An oluşturulan bir arabirim veya temsilci türüdürX(Of P1,...,Pn):

    • Tür parametresi Ai olarak Out bildirildiysePi, ters değişken olarak geçerli olur.

    • Tür parametresi Ai olarak In bildirildiysePi, aynı anda geçerli olur.

Aşağıdakiler bir arabirimde veya temsilci türünde ters değişken olarak geçerli olmalıdır:

  • Parametrenin türü.

  • Yöntem türü parametresinde tür kısıtlaması.

  • Bir erişimci varsa Set özelliğin türü.

  • Bir olayın türü.

Örneğin:

Delegate Function D(Of T, In U)(x As U) As T

Interface I1(Of In T)
End Interface

Interface I2(Of In T)
    ' OK, T is only used in an In position
    Sub M1(x As I1(Of T))

    ' Error: T is used in an Out position
    Function M2() As T
End Interface

Bir türün geçerli olması gereken durumlarda değişken türü parametresi kullanılamaz (hem hem de GetSet erişimcisi veya parametresi olan bir ByRef özellik gibi) değişken türü parametresi kullanılamaz.

Ko-ve kontra-varyans bir "elmas belirsizlik problemine" neden olur. Aşağıdaki kodu inceleyin:

Class C
    Implements IEnumerable(Of String)
    Implements IEnumerable(Of Exception)
     
    Public Function GetEnumerator1() As IEnumerator(Of String) _
       Implements IEnumerable(Of String).GetEnumerator
       Console.WriteLine("string")
    End Function
     
    Public Function GetEnumerator2() As IEnumerator(Of Exception) _
       Implements IEnumerable(Of Execption).GetEnumerator
       Console.WriteLine("exception")
    End Function
End Class
     
Dim c As IEnumerable(Of Object) = New C
c.GetEnumerator()

sınıfıC, hem öğesinden hem de öğesinden IEnumerable(Of String) birlikte değişken dönüştürme yoluyla IEnumerable(Of Exception)iki şekilde dönüştürülebilirIEnumerable(Of Object). CLR, iki yöntemden hangisinin tarafından c.GetEnumerator()çağrılacağını belirtmez. Genel olarak, bir sınıf ortak bir üst türe (örneğin, bu örnekte String ve Exception ortak üst Objecttüre sahip) sahip iki farklı genel bağımsız değişken ile birlikte değişken bir arabirim uygulamak üzere bildirildiğinde veya ortak bir alt türü olan iki farklı genel bağımsız değişkene sahip bir ters değişken arabirimi uygulamak için bir sınıf bildirildiğinde, belirsizlik ortaya çıkabilir. Derleyici, bu tür bildirimler hakkında bir uyarı verir.