Aracılığıyla paylaş


Dil bağımsızlığı ve dilden bağımsız bileşenler

.NET, dilden bağımsızdır. Bu, bir geliştirici olarak C#, F# ve Visual Basic gibi .NET uygulamalarını hedefleyen birçok dilden birinde geliştirme yapabileceğiniz anlamına gelir. .NET uygulamaları için geliştirilen sınıf kitaplıklarının türlerine ve üyelerine, başlangıçta yazıldıkları dili bilmek zorunda kalmadan ve özgün dil kurallarından herhangi birini izlemek zorunda kalmadan erişebilirsiniz. Bileşen geliştiricisiyseniz, bileşeninize dili ne olursa olsun herhangi bir .NET uygulaması tarafından erişilebilir.

Uyarı

Bu makalenin ilk bölümünde dilden bağımsız bileşenler, yani herhangi bir dilde yazılmış uygulamalar tarafından kullanılabilecek bileşenler oluşturma ele alınmaktadır. Ayrıca, birden çok dilde yazılmış kaynak kodundan tek bir bileşen veya uygulama da oluşturabilirsiniz; Bu makalenin ikinci bölümünde Diller Arası Birlikte Çalışabilirlik bölümüne bakın.

Herhangi bir dilde yazılmış diğer nesnelerle tam olarak etkileşime geçmek için, nesneler yalnızca tüm diller için ortak olan özellikleri çağıranlara göstermelidir. Bu ortak özellik kümesi, oluşturulan derlemelere uygulanan bir dizi kural olan Ortak Dil Belirtimi (CLS) tarafından tanımlanır. Ortak Dil Belirtimi, ECMA-335 Standart: Ortak Dil Altyapısı, Bölüm I, Maddeler 7'den 11'e kadar tanımlanır.

Bileşeniniz Ortak Dil Belirtimine uygunsa, CLS uyumlu olması garanti edilir ve CLS'yi destekleyen herhangi bir programlama dilinde yazılmış derlemelerde koddan erişilebilir. Kaynak kodunuz için CLSCompliantAttribute özniteliğini uygulayarak bileşeninizin derleme zamanında Ortak Dil Belirtimine uygun olup olmadığını belirleyebilirsiniz. Daha fazla bilgi için bkz. CLSCompliantAttribute özniteliği.

CLS uyumluluk kuralları

Bu bölümde CLS uyumlu bir bileşen oluşturma kuralları açıklanmıştır. Kuralların tam listesi için bkz. ECMA-335 Standart: Ortak Dil AltyapısıBölüm I, Yan Tümcesi 11.

Uyarı

Ortak Dil Belirtimi, tüketiciler (CLS uyumlu bir bileşene program aracılığıyla erişen geliştiriciler), çerçeveler (CLS uyumlu kitaplıklar oluşturmak için dil derleyicisi kullanan geliştiriciler) ve genişleticiler (dil derleyicisi veya CLS uyumlu bileşenler oluşturan kod ayrıştırıcısı gibi bir araç oluşturan geliştiriciler) için geçerli olduğundan CLS uyumluluğu için her kuralı ele alır. Bu makale, çerçeveler için geçerli olan kurallara odaklanır. Ancak, genişleticiler için geçerli olan bazı kuralların Reflection.Emitkullanılarak oluşturulan derlemelere de uygulanabileceğini unutmayın.

Dilden bağımsız bir bileşen tasarlamak için, yalnızca cls uyumluluğu kurallarını bileşeninizin genel arabirimine uygulamanız gerekir. Özel uygulamanızın belirtime uyması gerekmez.

Önemli

CLS uyumluluğu kuralları, özel uygulaması için değil, yalnızca bir bileşenin ortak arabirimi için geçerlidir.

Örneğin, Byte dışındaki işaretsiz tamsayılar CLS uyumlu değildir. Aşağıdaki örnekteki Person sınıfı Agetüründe bir UInt16 özelliği gösterdiğinden, aşağıdaki kod bir derleyici uyarısı görüntüler.

using System;

[assembly: CLSCompliant(true)]

public class Person
{
   private UInt16 personAge = 0;

   public UInt16 Age
   { get { return personAge; } }
}
// The attempt to compile the example displays the following compiler warning:
//    Public1.cs(10,18): warning CS3003: Type of 'Person.Age' is not CLS-compliant
<Assembly: CLSCompliant(True)>

Public Class Person
    Private personAge As UInt16

    Public ReadOnly Property Age As UInt16
        Get
            Return personAge
        End Get
    End Property
End Class
' The attempt to compile the example displays the following compiler warning:
'    Public1.vb(9) : warning BC40027: Return type of function 'Age' is not CLS-compliant.
'    
'       Public ReadOnly Property Age As UInt16
'                                ~~~

Person olan Age özelliğinin türünü CLS uyumlu, 16 bit işaretli bir tamsayı olan UInt16olarak değiştirerek Int16 sınıfıNı CLS uyumlu yapabilirsiniz. Özel personAge alanının türünü değiştirmeniz gerekmez.

using System;

[assembly: CLSCompliant(true)]

public class Person
{
   private Int16 personAge = 0;

   public Int16 Age
   { get { return personAge; } }
}
<Assembly: CLSCompliant(True)>

Public Class Person
    Private personAge As UInt16

    Public ReadOnly Property Age As Int16
        Get
            Return CType(personAge, Int16)
        End Get
    End Property
End Class

Kitaplığın genel arabirimi aşağıdakilerden oluşur:

  • Genel sınıflar tanımları.

  • Genel sınıfların genel üyelerinin tanımları ve türetilmiş sınıflar (korumalı üyeler) tarafından erişilebilen üyelerin tanımları.

  • Herkese açık sınıfların herkese açık yöntemlerinin parametreleri ve dönüş türleri ile türetilmiş sınıflar tarafından erişilebilen yöntemlerin parametreleri ve dönüş türleri.

CLS uyumluluğu kuralları aşağıdaki tabloda listelenmiştir. Kurallar metni, Ecma International'ın Telif Hakkı 2012 olan ECMA-335 Standard: Common Language Infrastructurebölümünden ayrıntılı olarak alınmıştır. Bu kurallar hakkında daha ayrıntılı bilgi aşağıdaki bölümlerde bulunur.

Kategori Bak Kural Kural Numarası
Erişilebilirlik Üye erişilebilirliği Kalıtım yoluyla alınan yöntemler geçersiz kılınırken erişilebilirlik, yalnızca farklı bir derlemeye ait olan ve erişilebilirlik family-or-assemblyile devralınan bir yöntem geçersiz kılındığı durumlarda değişmez. Bu durumda, geçersiz kılmanın erişilebilirliği familyolmalıdır. 10
Erişilebilirlik Üye erişilebilirliği Türlerin ve üyelerin görünürlüğü ve erişilebilirliği, herhangi bir üyenin bildiriminde yer alan türlerin, üyenin kendisi görünür ve erişilebilir olduğunda görünür ve erişilebilir olacak şekilde düzenlenmelidir. Örneğin, derlemesi dışında görülebilen genel bir yöntem, türü yalnızca kendi derlemesi içinde görülebilen bir bağımsız değişkene sahip olmamalıdır. Herhangi bir üyenin imzasında kullanılan örneklenmiş bir genel türü oluşturan türler, üyenin kendisi ne zaman görünür ve erişilebilir olursa, o zaman görünür ve erişilebilir olacaktır. Örneğin, derlemesinin dışında erişilebilen bir üyenin imzasında bulunan örneklenen genel tür, türü yalnızca derleme içinde erişilebilen genel bir bağımsız değişkenin türüne sahip olmamalıdır. 12
Diziler Diziler Diziler CLS uyumlu bir türe sahip öğelere sahip olmalı ve dizinin tüm boyutları sıfırdan daha düşük sınırlara sahip olmalıdır. Yalnızca bir öğenin bir dizi olduğu gerçeği ve aşırı yüklemeleri ayırt etmek için dizinin öğe türü gereklidir. Aşırı yükleme iki veya daha fazla dizi türünü temel alırsa, öğe türleri tür olarak adlandırılır. 16
Özellikler Öznitelikler Öznitelikler System.Attributetüründe veya ondan devralan bir tür olmalıdır. 41
Özellikler Öznitelikler CLS yalnızca özel özniteliklerin kodlamalarının bir alt kümesine izin verir. Bu kodlamalarda görünecek tek türler şunlardır (bkz. Bölüm IV): System.Type, System.String, System.Char, System.Boolean, System.Byte, System.Int16, System.Int32, System.Int64, System.Single, System.Doubleve CLS uyumlu bir temel tamsayı türüne dayalı herhangi bir numaralandırma türü. 34
Özellikler Öznitelikler CLS, genel olarak görünen gerekli değiştiricilere (modreq, bölüm II'ye bakın) izin vermez, ancak anlamadığı isteğe bağlı değiştiricilere (modopt, bkz. Bölüm II) izin verir. 35
Kurucular Yapıcılar Nesne oluşturucu, devralınan örnek verilerine erişim gerçekleşmeden önce temel sınıfının bazı örnek oluşturucularını çağıracaktır. (Bu, oluşturucuları olmayan değer türleri için geçerli değildir.) 21
Kurucular Yapıcılar Nesne oluşturucu, bir nesnenin oluşturulmasının bir parçası dışında çağrılmaz ve bir nesne iki kez başlatılmaz. 22
Numaralandırma Sıralamalar Enum'un temel türü yerleşik bir CLS tamsayı türü olmalı, alanın adı "value__" olmalı ve bu alan RTSpecialNameolarak işaretlenmelidir. 7
Numaralandırma Sıralamalar System.FlagsAttribute (bkz. Bölüm IV Kitaplığı) özel özniteliğinin varlığı veya yokluğuyla gösterilen iki ayrı enum türü vardır. Biri adlandırılmış tamsayı değerlerini temsil eder; diğeri, adlandırılmamış bir değer oluşturmak için birleştirilebilen adlandırılmış bit bayraklarını temsil eder. bir enum değeri belirtilen değerlerle sınırlı değildir. 8
Numaralandırma Sıralamalar Enum'un sabit alanları kendi türünde olmalıdır. 9
Etkinlikler Etkinlikler Bir olayı uygulayan yöntemler meta verilerde SpecialName olarak işaretlenmelidir. 29
Etkinlikler Etkinlikler Bir olayın ve onun erişimcilerinin erişilebilirliği aynı olmalıdır. 30
Etkinlikler Etkinlikler Bir etkinlik için add ve remove yöntemleri ya ikisi de mevcut olmalı ya da ikisi de bulunmamalıdır. 31
Etkinlikler Etkinlikler Bir olayın add ve remove metodu, türü olayın türünü tanımlayan ve System.Delegate türetilecek bir parametre alacaktır. 32
Etkinlikler Etkinlikler Olaylar belirli bir adlandırma düzenine uymalıdır. CLS kural 29'da belirtilen SpecialName özniteliği, uygun ad karşılaştırmalarında yoksayılır ve tanımlayıcı kurallarına uyulmalıdır. 33
Özel durumlar İstisnalar Fırlatılan nesneler, System.Exception türünde veya ondan devralan bir tür olmalıdır. Bununla birlikte, diğer özel durum türlerinin yayılmasını engellemek için CLS uyumlu yöntemler gerekli değildir. 40
Genel CLS uyumluluk kuralları CLS kuralları yalnızca bir türün, tanımlama derlemesinin dışında erişilebilir veya görünür olan bölümleri için geçerlidir. 1
Genel CLS uyumluluk kuralları CLS uyumlu olmayan türlerin üyeleri CLS uyumlu olarak işaretlenmez. 2
Genel Türler Genel türler ve üyeler İç içe türlerin, kapsayıcı tür ile en az aynı sayıda genel parametreye sahip olması gerekir. İç içe geçmiş bir türdeki genel parametreler, onu kapsayan türün genel parametreleriyle konum açısından karşılık gelir. 42
Genel Türler Genel türler ve üyeler Genel bir türün adı, yukarıda tanımlanan kurallara göre iç içe olmayan türde bildirilen veya iç içe yerleştirilmişse türe yeni eklenen tür parametrelerinin sayısını kodlayacaktır. 43
Genel Türler Genel türler ve üyeler Genel bir tür, temel türe veya arabirimlere getirilen herhangi bir kısıtlamanın genel türün kısıtlamaları tarafından karşılanmasını garanti etmek için yeterli kısıtlamaları yeniden ilan etmelidir. 44
Genel Türler Genel türler ve üyeler Genel parametrelerde kısıtlama olarak kullanılan türler CLS uyumlu olmalıdır. 45
Genel Türler Genel türler ve üyeler Örneklenmiş bir genel türdeki üyelerin (iç içe türler dahil) görünürlüğü ve erişilebilirliği, genel tür bildirimi yerine belirli bir örnekleme için kapsamlanmış olarak kabul edilmelidir. Bunu varsayarsak, CLS kuralı 12'nin görünürlük ve erişilebilirlik kuralları geçerli olmaya devam eder. 46
Genel Türler Genel türler ve üyeler Her soyut veya sanal genel yöntem için varsayılan somut (kısıtlanmamış) bir uygulama olmalıdır 47
Arayüzler Arayüzler CLS uyumlu arabirimlerin uygulanması için CLS uyumlu olmayan yöntemlerin tanımlanması gerekmez. 18
Arayüzler Arayüzler CLS uyumlu arabirimler statik yöntemleri tanımlamaz ve alanları tanımlamaz. 19
Üyeler Genel Tip üyeleri Genel statik alanlar ve yöntemler CLS uyumlu değildir. 36
Üyeler -- Sabit statik değeri, alan başlatma meta verileri kullanılarak belirtilir. CLS uyumlu bir değişmez değer, alan başlatma meta verilerinde, değişmez değer ile tam olarak aynı türde bir değere sahip olmalıdır. Eğer bu değişmez değer bir enumise, temel türle aynı türde bir değere sahip olmalıdır. 13 (on üç)
Üyeler Genel Tip üyeleri Vararg kısıtlaması CLS'nin bir parçası değildir ve CLS tarafından desteklenen tek çağırma kuralı standart yönetilen çağrı kuralıdır. 15
Adlandırma kuralları Adlandırma kuralları Bütünleştirmeler, tanımlayıcıların başlatılmasına ve dahil edilmesine izin verilen karakter kümesini yöneten Unicode Standardı 3.0'ın Teknik Rapor 15'in Ek 7'sini izlemelidir ve bu, çevrimiçi olarak Unicode Normalleştirme Formlarıadresinden sağlanabilir. Tanımlayıcılar, Unicode Normalleştirme Formu C tarafından tanımlanan kurallı biçimde olmalıdır. CLS amacıyla, küçük harf eşlemeleri (Unicode yerel ayara duyarsız, bire bir küçük harf eşlemeleri tarafından belirtildiği gibi) aynıysa iki tanımlayıcı aynıdır. Diğer bir ifadeyle, CLS kapsamında iki tanımlayıcının farklı olarak kabul edilmesi için, sadece büyük/küçük harf farklılığı bulunması yeterli değildir. Ancak, devralınan bir tanımı geçersiz kılmak için CLI, özgün bildirimin tam kodlamasının kullanılmasını gerektirir. 4
Aşırı Yükleme Adlandırma kuralları CLS uyumlu bir kapsamda tanıtılan tüm adlar, adların aynı olduğu ve aşırı yükleme yoluyla çözümlendiği durumlar dışında, türünden bağımsız olmalıdır. Yani, CTS tek bir türün bir yöntem ve alan için aynı adı kullanmasına izin verirken, CLS bunu yapmaz. 5
Aşırı Yükleme Adlandırma kuralları CTS'nin ayrı imzaların ayırt edilmesine izin vermesine rağmen, alanlar ve iç içe türler yalnızca tanımlayıcı karşılaştırmasıyla ayırt edilmelidir. Aynı ada sahip yöntemler, özellikler ve olaylar (tanımlayıcı karşılaştırması ile) sadece dönüş türüyle değil, başka yönlerden de farklı olmalıdır, CLS Kural 39'da belirtilenler dışında 6
Aşırı Yükleme Aşırı Yükleme Yalnızca özellikler ve yöntemler aşırı yüklenebilir. 37
Aşırı Yükleme Aşırı Yükleme op_Implicit ve op_Explicitadlı dönüştürme işleçleri dışında, özellikler ve yöntemler yalnızca parametrelerinin sayısına ve türlerine göre aşırı yüklenebilir. Bu işleçler, dönüş türlerine göre de aşırı yüklenebilir. 38
Aşırı Yükleme -- Bir türde bildirilen iki veya daha fazla CLS uyumlu yöntem aynı ada sahipse ve belirli bir tür örnekleme kümesi için aynı parametreye ve dönüş türlerine sahipse, tüm bu yöntemler bu tür örneklemelerinde eş değerde olacaktır. 48
Özellikler Özellikler Bir özelliğin alıcı ve ayarlayıcı yöntemlerini uygulayan yöntemler meta verilerde SpecialName işaretlenir. yirmi dört
Özellikler Özellikler Bir özelliğin erişimcilerinin tümü statik, tümü sanal veya tümü örnek olmalıdır. 26
Özellikler Özellikler Bir özelliğin türü, alıcının dönüş türü ve ayarlayıcının son bağımsız değişkeninin türü olmalıdır. Özelliğin parametrelerinin türleri, alıcının parametre türleri ve ayarlayıcının son parametresi hariç tüm parametrelerin türleri olacaktır. Bu türlerin tümü CLS uyumlu olmalı ve yönetilen işaretçi olmamalıdır; yani referansla geçiş yapılmamalıdır. 27
Özellikler Özellikler Özellikler belirli bir adlandırma düzenine uymalıdır. CLS kural 24'te belirtilen SpecialName özniteliği, uygun isim karşılaştırmalarında yoksayılır ve tanımlayıcı kurallarına uymalıdır. Bir özelliğin getter yöntemi, ayarlayıcı yöntemi veya her ikisi de olmalıdır. 28
Tür dönüştürme Tür dönüştürme op_Implicit veya op_Explicit sağlanırsa, zorlamayı sağlamanın alternatif bir aracı sağlanacaktır. 39
Türler Türleri ve tür üyelerinin imzaları Kutulanmış değer türleri CLS uyumlu değildir. 3
Türler Türleri ve tür üyelerinin imzaları İmzada görünen tüm türler CLS uyumlu olmalıdır. Örneklenmiş genel tür oluşturan tüm türler CLS uyumlu olmalıdır. 11
Türler Türleri ve tür üyelerinin imzaları Tipli referanslar CLS uyumlu değildir. 14
Türler Türleri ve tür üyelerinin imzaları Yönetilmeyen işaretçi türleri CLS uyumlu değildir. 17
Türler Türleri ve tür üyelerinin imzaları CLS uyumlu sınıflar, değer türleri ve arabirimler CLS uyumlu olmayan üyelerin uygulanmasını gerektirmeyecektir 20
Türler Türleri ve tür üyelerinin imzaları System.Object CLS uyumlu. Diğer CLS uyumlu sınıflar CLS uyumlu bir sınıftan devralmalıdır. 23

Alt bölümlere dizin oluşturma:

Türler ve tür üyesi imzaları

System.Object türü CLS uyumludur ve .NET tür sistemindeki tüm nesne türlerinin temel türüdür. .NET'te devralma örtüktür (örneğin, String sınıfı örtük olarak Object sınıfından devralır) veya açık (örneğin, CultureNotFoundException sınıfı açıkça Exception sınıfından devralan ArgumentException sınıfından devralır. Türetilmiş bir türün CLS uyumlu olması için, temel türünün de CLS uyumlu olması gerekir.

Aşağıdaki örnekte, temel türü CLS uyumlu olmayan türetilmiş bir tür gösterilmektedir. Sayaç olarak işaretsiz bir 32 bit tamsayı kullanan bir temel Counter sınıfı tanımlar. sınıfı işaretsiz bir tamsayı sarmalayarak sayaç işlevi sağladığından, sınıf CLS uyumlu değil olarak işaretlenir. Sonuç olarak, NonZeroCountertüretilmiş bir sınıf da CLS uyumlu değildir.

using System;

[assembly: CLSCompliant(true)]

[CLSCompliant(false)]
public class Counter
{
   UInt32 ctr;

   public Counter()
   {
      ctr = 0;
   }

   protected Counter(UInt32 ctr)
   {
      this.ctr = ctr;
   }

   public override string ToString()
   {
      return String.Format("{0}). ", ctr);
   }

   public UInt32 Value
   {
      get { return ctr; }
   }

   public void Increment()
   {
      ctr += (uint) 1;
   }
}

public class NonZeroCounter : Counter
{
   public NonZeroCounter(int startIndex) : this((uint) startIndex)
   {
   }

   private NonZeroCounter(UInt32 startIndex) : base(startIndex)
   {
   }
}
// Compilation produces a compiler warning like the following:
//    Type3.cs(37,14): warning CS3009: 'NonZeroCounter': base type 'Counter' is not
//            CLS-compliant
//    Type3.cs(7,14): (Location of symbol related to previous warning)
<Assembly: CLSCompliant(True)>

<CLSCompliant(False)> _
Public Class Counter
    Dim ctr As UInt32

    Public Sub New
        ctr = 0
    End Sub

    Protected Sub New(ctr As UInt32)
        ctr = ctr
    End Sub

    Public Overrides Function ToString() As String
        Return String.Format("{0}). ", ctr)
    End Function

    Public ReadOnly Property Value As UInt32
        Get
            Return ctr
        End Get
    End Property

    Public Sub Increment()
        ctr += CType(1, UInt32)
    End Sub
End Class

Public Class NonZeroCounter : Inherits Counter
    Public Sub New(startIndex As Integer)
        MyClass.New(CType(startIndex, UInt32))
    End Sub

    Private Sub New(startIndex As UInt32)
        MyBase.New(CType(startIndex, UInt32))
    End Sub
End Class
' Compilation produces a compiler warning like the following:
'    Type3.vb(34) : warning BC40026: 'NonZeroCounter' is not CLS-compliant 
'    because it derives from 'Counter', which is not CLS-compliant.
'    
'    Public Class NonZeroCounter : Inherits Counter
'                 ~~~~~~~~~~~~~~

Bir yöntemin dönüş türü veya özellik türü de dahil olmak üzere üye imzalarında görünen tüm türler CLS uyumlu olmalıdır. Ayrıca, genel türler için:

  • Örneklenmiş genel tür oluşturan tüm türler CLS uyumlu olmalıdır.

  • Genel parametrelerde kısıtlama olarak kullanılan tüm türler CLS uyumlu olmalıdır.

.NET ortak tür sistemi, doğrudan ortak dil çalışma zamanı tarafından desteklenen ve özel olarak bir derlemenin meta verilerinde kodlanmış birçok yerleşik tür içerir. Bu iç türlerden, aşağıdaki tabloda listelenen türler CLS uyumludur.

CLS uyumlu tür Açıklama
Bayt 8 bit işaretsiz tamsayı
int16 16 bit işaretli tamsayı
int32 32 bit imzalı tamsayı
Int64 64 bit işaretli tamsayı
Yarım Yarım hassasiyetli kayan nokta değeri
Tek Tek hassasiyetli kayan nokta değeri
Çift Çift duyarlıklı kayan nokta değeri
Boolean doğru veya yanlış değer türü
Char UTF-16 kodlanmış kod birimi
Ondalık Kayan nokta olmayan ondalık sayı
IntPtr Platform tarafından tanımlanan boyutta bir işaretçi veya tutamacı
Dizgi Sıfır, bir veya daha fazla Char nesnesi koleksiyonu

Aşağıdaki tabloda listelenen iç türler CLS Uyumlu değildir.

Uyumlu olmayan tür Açıklama CLS uyumlu alternatif
SByte 8 bit imzalı tamsayı veri türü int16
UInt16 16 bit işaretsiz tamsayı int32
UInt32 32 bit işaretsiz tamsayı Int64
UInt64 64 bit işaretsiz tamsayı Int64 (taşabilir), BigIntegerveya Double
UIntPtr İmzasız işaretçi veya kulp IntPtr

.NET Sınıf Kitaplığı veya başka bir sınıf kitaplığı CLS uyumlu olmayan başka türler içerebilir, örneğin:

  • Kutulanmış değer türleri. Aşağıdaki C# örneği, int*adlı Value türünde ortak özelliği olan bir sınıf oluşturur. int* kutulanmış bir değer türü olduğundan, derleyici bunu CLS uyumlu değil olarak işaretler.

    using System;
    
    [assembly:CLSCompliant(true)]
    
    public unsafe class TestClass
    {
       private int* val;
    
       public TestClass(int number)
       {
          val = (int*) number;
       }
    
       public int* Value {
          get { return val; }
       }
    }
    // The compiler generates the following output when compiling this example:
    //        warning CS3003: Type of 'TestClass.Value' is not CLS-compliant
    
  • Bir nesneye referans ve bir türe referans içeren özel yapılar olan türlendirilmiş referanslar. Yazılan referanslar .NET'te TypedReference sınıfı tarafından temsil edilir.

Bir tür CLS uyumlu değilse, CLSCompliantAttribute özniteliğini isCompliant değeri false olan bir şekilde uygulamanız gerekir. Daha fazla bilgi için CLSCompliantAttribute özniteliği bölümüne bakın.

Aşağıdaki örnek, bir yöntem imzasında ve genel tür örneklemesinde CLS uyumluluğu sorununu göstermektedir. InvoiceItemtüründe bir özelliği, UInt32türünde bir özelliği ve Nullable<UInt32> ve UInt32türünde parametreleri olan bir oluşturucu ile bir Nullable<UInt32> sınıfı tanımlar. Bu örneği derlemeye çalıştığınızda dört derleyici uyarısı alırsınız.

using System;

[assembly: CLSCompliant(true)]

public class InvoiceItem
{
   private uint invId = 0;
   private uint itemId = 0;
   private Nullable<uint> qty;

   public InvoiceItem(uint sku, Nullable<uint> quantity)
   {
      itemId = sku;
      qty = quantity;
   }

   public Nullable<uint> Quantity
   {
      get { return qty; }
      set { qty = value; }
   }

   public uint InvoiceId
   {
      get { return invId; }
      set { invId = value; }
   }
}
// The attempt to compile the example displays the following output:
//    Type1.cs(13,23): warning CS3001: Argument type 'uint' is not CLS-compliant
//    Type1.cs(13,33): warning CS3001: Argument type 'uint?' is not CLS-compliant
//    Type1.cs(19,26): warning CS3003: Type of 'InvoiceItem.Quantity' is not CLS-compliant
//    Type1.cs(25,16): warning CS3003: Type of 'InvoiceItem.InvoiceId' is not CLS-compliant
<Assembly: CLSCompliant(True)>

Public Class InvoiceItem

    Private invId As UInteger = 0
    Private itemId As UInteger = 0
    Private qty AS Nullable(Of UInteger)

    Public Sub New(sku As UInteger, quantity As Nullable(Of UInteger))
        itemId = sku
        qty = quantity
    End Sub

    Public Property Quantity As Nullable(Of UInteger)
        Get
            Return qty
        End Get
        Set
            qty = value
        End Set
    End Property

    Public Property InvoiceId As UInteger
        Get
            Return invId
        End Get
        Set
            invId = value
        End Set
    End Property
End Class
' The attempt to compile the example displays output similar to the following:
'    Type1.vb(13) : warning BC40028: Type of parameter 'sku' is not CLS-compliant.
'    
'       Public Sub New(sku As UInteger, quantity As Nullable(Of UInteger))
'                      ~~~
'    Type1.vb(13) : warning BC40041: Type 'UInteger' is not CLS-compliant.
'    
'       Public Sub New(sku As UInteger, quantity As Nullable(Of UInteger))
'                                                               ~~~~~~~~
'    Type1.vb(18) : warning BC40041: Type 'UInteger' is not CLS-compliant.
'    
'       Public Property Quantity As Nullable(Of UInteger)
'                                               ~~~~~~~~
'    Type1.vb(27) : warning BC40027: Return type of function 'InvoiceId' is not CLS-compliant.
'    
'       Public Property InvoiceId As UInteger
'                       ~~~~~~~~~

Derleyici uyarılarını ortadan kaldırmak için, InvoiceItem ortak arabirimindeki CLS uyumlu olmayan türleri uyumlu türlerle değiştirin:

using System;

[assembly: CLSCompliant(true)]

public class InvoiceItem
{
   private uint invId = 0;
   private uint itemId = 0;
   private Nullable<int> qty;

   public InvoiceItem(int sku, Nullable<int> quantity)
   {
      if (sku <= 0)
         throw new ArgumentOutOfRangeException("The item number is zero or negative.");
      itemId = (uint) sku;

      qty = quantity;
   }

   public Nullable<int> Quantity
   {
      get { return qty; }
      set { qty = value; }
   }

   public int InvoiceId
   {
      get { return (int) invId; }
      set {
         if (value <= 0)
            throw new ArgumentOutOfRangeException("The invoice number is zero or negative.");
         invId = (uint) value; }
   }
}
<Assembly: CLSCompliant(True)>

Public Class InvoiceItem

    Private invId As UInteger = 0
    Private itemId As UInteger = 0
    Private qty AS Nullable(Of Integer)

    Public Sub New(sku As Integer, quantity As Nullable(Of Integer))
        If sku <= 0 Then
            Throw New ArgumentOutOfRangeException("The item number is zero or negative.")
        End If
        itemId = CUInt(sku)
        qty = quantity
    End Sub

    Public Property Quantity As Nullable(Of Integer)
        Get
            Return qty
        End Get
        Set
            qty = value
        End Set
    End Property

    Public Property InvoiceId As Integer
        Get
            Return CInt(invId)
        End Get
        Set
            invId = CUInt(value)
        End Set
    End Property
End Class

Listelenen belirli türlere ek olarak, bazı tür kategorileri CLS uyumlu değildir. Bunlar yönetilmeyen işaretçi türlerini ve işlev işaretçisi türlerini içerir. Aşağıdaki örnek, bir tamsayı dizisi oluşturmak için bir tamsayı işaretçisi kullandığından derleyici uyarısı oluşturur.

using System;

[assembly: CLSCompliant(true)]

public class ArrayHelper
{
   unsafe public static Array CreateInstance(Type type, int* ptr, int items)
   {
      Array arr = Array.CreateInstance(type, items);
      int* addr = ptr;
      for (int ctr = 0; ctr < items; ctr++) {
          int value = *addr;
          arr.SetValue(value, ctr);
          addr++;
      }
      return arr;
   }
}
// The attempt to compile this example displays the following output:
//    UnmanagedPtr1.cs(8,57): warning CS3001: Argument type 'int*' is not CLS-compliant

CLS uyumlu soyut sınıflar için (yani, C# dilinde abstract olarak veya Visual Basic'te MustInherit olarak işaretlenmiş sınıflar), sınıfın tüm üyeleri de CLS uyumlu olmalıdır.

Adlandırma kuralları

Bazı programlama dilleri büyük/küçük harfe duyarsız olduğundan, tanımlayıcılar (ad alanlarının, türlerin ve üyelerin adları gibi) büyük/küçük harf dışında başka bir şekilde farklılık göstermelidir. Küçük harf eşlemeleri aynıysa iki tanımlayıcı eşdeğer olarak kabul edilir. Aşağıdaki C# örneği, Person ve personiki genel sınıfı tanımlar. Yalnızca büyük/küçük harf farkıyla farklı olduklarından, C# derleyicisi bu türleri CLS uyumlu değil olarak işaretler.

using System;

[assembly: CLSCompliant(true)]

public class Person : person
{
}

public class person
{
}
// Compilation produces a compiler warning like the following:
//    Naming1.cs(11,14): warning CS3005: Identifier 'person' differing
//                       only in case is not CLS-compliant
//    Naming1.cs(6,14): (Location of symbol related to previous warning)

Ad alanlarının, türlerin ve üyelerin adları gibi programlama dili tanımlayıcılarının Unicode Standartuyması gerekir. Bu, şu anlama gelir:

  • Tanımlayıcının ilk karakteri herhangi bir Unicode büyük harfi, küçük harfi, başlık harfi, değiştirici harf, diğer harf veya harf numarası olabilir. Unicode karakter kategorileri hakkında bilgi için bkz. System.Globalization.UnicodeCategory numaralandırması.

  • Sonraki karakterler, ilk karakterin dahil olduğu kategorilerden herhangi birinden olabilir ve ayrıca boşluk bırakan olmayan işaretler, boşluk birleştirici işaretler, ondalık sayılar, bağlayıcı noktalama işaretleri ve biçimlendirme kodlarını da içerebilir.

Tanımlayıcıları karşılaştırmadan önce biçimlendirme kodlarını filtrelemeniz ve tanımlayıcıları Unicode Normalleştirme Formu C'ye dönüştürmeniz gerekir çünkü tek bir karakter birden çok UTF-16 kod birimiyle temsil edilebilir. Unicode Normalleştirme Formu C'de aynı kod birimlerini üreten karakter dizileri CLS uyumlu değildir. Aşağıdaki örnek, ANGSTROM İŞARETİ (U+212B) karakterinden oluşan adlı bir özelliği ve Åadlı ikinci bir özelliği tanımlar. Bu özellik, ÜSTÜNDE HALKA BULUNAN LATIN BÜYÜK HARF A karakterinden oluşur (U+00C5). Hem C# hem de Visual Basic derleyicileri kaynak kodu CLS uyumlu değil olarak işaretler.

public class Size
{
   private double a1;
   private double a2;

   public double Å
   {
       get { return a1; }
       set { a1 = value; }
   }

   public double Å
   {
       get { return a2; }
       set { a2 = value; }
   }
}
// Compilation produces a compiler warning like the following:
//    Naming2a.cs(16,18): warning CS3005: Identifier 'Size.Å' differing only in case is not
//            CLS-compliant
//    Naming2a.cs(10,18): (Location of symbol related to previous warning)
//    Naming2a.cs(18,8): warning CS3005: Identifier 'Size.Å.get' differing only in case is not
//            CLS-compliant
//    Naming2a.cs(12,8): (Location of symbol related to previous warning)
//    Naming2a.cs(19,8): warning CS3005: Identifier 'Size.Å.set' differing only in case is not
//            CLS-compliant
//    Naming2a.cs(13,8): (Location of symbol related to previous warning)
<Assembly: CLSCompliant(True)>
Public Class Size
    Private a1 As Double
    Private a2 As Double

    Public Property Å As Double
        Get
            Return a1
        End Get
        Set
            a1 = value
        End Set
    End Property

    Public Property Å As Double
        Get
            Return a2
        End Get
        Set
            a2 = value
        End Set
    End Property
End Class
' Compilation produces a compiler warning like the following:
'    Naming1.vb(9) : error BC30269: 'Public Property Å As Double' has multiple definitions
'     with identical signatures.
'    
'       Public Property Å As Double
'                       ~

Belirli bir kapsamdaki üye adları (derleme içindeki ad alanları, ad alanı içindeki türler veya bir tür içindeki üyeler gibi), aşırı yükleme yoluyla çözümlenen adlar dışında benzersiz olmalıdır. Bu gereksinim, bir kapsamdaki birden çok üyenin farklı üye türleri olduğu sürece aynı adlara sahip olmasını sağlayan ortak tür sisteminden daha sıkıdır (örneğin, biri bir yöntem, biri bir alan). Özellikle, tür üyeleri için:

  • Alanlar ve iç içe türler yalnızca adla ayırt edilir.

  • Aynı ada sahip yöntemler, özellikler ve olaylar yalnızca dönüş türünden daha fazla şekilde farklılık göstermelidir.

Aşağıdaki örnek, üye adlarının kapsamları içinde benzersiz olması gereksinimini gösterir. Converteradlı dört üye içeren Conversion adlı bir sınıf tanımlar. Üç yöntemdir ve biri bir özelliktir. bir Int64 parametresi içeren yöntem benzersiz olarak adlandırılır, ancak Int32 parametresine sahip iki yöntem değildir, çünkü dönüş değeri üyenin imzasının bir parçası olarak kabul edilmez. Conversion özelliği de bu gereksinimi ihlal eder çünkü özellikler aşırı yüklenmiş yöntemlerle aynı ada sahip olamaz.

using System;

[assembly: CLSCompliant(true)]

public class Converter
{
   public double Conversion(int number)
   {
      return (double) number;
   }

   public float Conversion(int number)
   {
      return (float) number;
   }

   public double Conversion(long number)
   {
      return (double) number;
   }

   public bool Conversion
   {
      get { return true; }
   }
}
// Compilation produces a compiler error like the following:
//    Naming3.cs(13,17): error CS0111: Type 'Converter' already defines a member called
//            'Conversion' with the same parameter types
//    Naming3.cs(8,18): (Location of symbol related to previous error)
//    Naming3.cs(23,16): error CS0102: The type 'Converter' already contains a definition for
//            'Conversion'
//    Naming3.cs(8,18): (Location of symbol related to previous error)
<Assembly: CLSCompliant(True)>

Public Class Converter
    Public Function Conversion(number As Integer) As Double
        Return CDbl(number)
    End Function

    Public Function Conversion(number As Integer) As Single
        Return CSng(number)
    End Function

    Public Function Conversion(number As Long) As Double
        Return CDbl(number)
    End Function

    Public ReadOnly Property Conversion As Boolean
        Get
            Return True
        End Get
    End Property
End Class
' Compilation produces a compiler error like the following:
'    Naming3.vb(8) : error BC30301: 'Public Function Conversion(number As Integer) As Double' 
'                    and 'Public Function Conversion(number As Integer) As Single' cannot 
'                    overload each other because they differ only by return types.
'    
'       Public Function Conversion(number As Integer) As Double
'                       ~~~~~~~~~~
'    Naming3.vb(20) : error BC30260: 'Conversion' is already declared as 'Public Function 
'                     Conversion(number As Integer) As Single' in this class.
'    
'       Public ReadOnly Property Conversion As Boolean
'                                ~~~~~~~~~~

Tek tek diller benzersiz anahtar sözcükler içerir, bu nedenle ortak dil çalışma zamanını hedefleyen dillerin anahtar sözcüklerle çakışan tanımlayıcılara (tür adları gibi) başvurmak için de bazı mekanizmalar sağlaması gerekir. Örneğin, case hem C# hem de Visual Basic'te bir anahtar sözcüktür. Ancak aşağıdaki Visual Basic örneği, açma ve kapatma küme ayraçlarını kullanarak, case adlı sınıfın case anahtar sözcüğünden olan belirsizliğini giderir. Aksi takdirde, örnek "Anahtar sözcük tanımlayıcı olarak geçerli değil" hata iletisini oluşturur ve derlenmez.

Public Class [case]
    Private _id As Guid
    Private name As String

    Public Sub New(name As String)
        _id = Guid.NewGuid()
        Me.name = name
    End Sub

    Public ReadOnly Property ClientName As String
        Get
            Return name
        End Get
    End Property
End Class

Aşağıdaki C# örneği, case sınıfını, tanımlayıcıyı dil anahtar sözcüğünden ayırt etmek için @ simgesini kullanarak başlatabiliyor. Bu olmadan, C# derleyicisi, "Tür bekleniyor" ve "Geçersiz ifade terimi: 'case'" şeklinde iki hata mesajı görüntüler.

using System;

public class Example
{
   public static void Main()
   {
      @case c = new @case("John");
      Console.WriteLine(c.ClientName);
   }
}

Tür dönüştürme

Ortak Dil Belirtimi iki dönüştürme işleci tanımlar:

  • op_Implicit, veri veya duyarlık kaybına neden olmayan dönüştürmelerin genişletilmesi için kullanılır. Örneğin, Decimal yapısı, tam sayı türlerinin ve op_Implicit değerlerinin değerlerini Char değerlere dönüştürmek için aşırı yüklenmiş bir Decimal işleci içerir.

  • op_Explicit, büyüklük kaybına (değer daha küçük bir aralığa sahip bir değere dönüştürülür) veya duyarlık kaybına neden olabilecek dönüştürmeleri daraltmak için kullanılır. Örneğin, Decimal yapısı, op_Explicit ve Double değerlerini Single dönüştürmek ve Decimal değerleri Decimal, Doubleve Singleintegral değerlerine dönüştürmek için aşırı yüklenmiş bir Char işleci içerir.

Ancak, tüm diller işleç aşırı yüklemesini veya özel işleçlerin tanımını desteklemez. Bu dönüştürme işleçlerini uygulamayı seçerseniz, dönüştürmeyi gerçekleştirmek için alternatif bir yol da sağlamanız gerekir. From Xxx ve ToXxx yöntemleri sağlamanızı öneririz.

Aşağıdaki örnek CLS uyumlu örtük ve açık dönüştürmeleri tanımlar. İmzasız, çift duyarlıklı, kayan noktalı bir sayıyı temsil eden bir UDouble sınıfı oluşturur. UDouble'den Double'a örtük dönüştürmeler ve UDouble'den Single'a, DoubleUDouble'a ve SingleUDouble'a açık dönüştürmeler sağlar. Ayrıca örtük dönüştürme işlecine alternatif olarak bir ToDouble yöntemi ve açık dönüştürme işleçlerine alternatif olarak ToSingle, FromDoubleve FromSingle yöntemlerini tanımlar.

using System;

public struct UDouble
{
   private double number;

   public UDouble(double value)
   {
      if (value < 0)
         throw new InvalidCastException("A negative value cannot be converted to a UDouble.");

      number = value;
   }

   public UDouble(float value)
   {
      if (value < 0)
         throw new InvalidCastException("A negative value cannot be converted to a UDouble.");

      number = value;
   }

   public static readonly UDouble MinValue = (UDouble) 0.0;
   public static readonly UDouble MaxValue = (UDouble) Double.MaxValue;

   public static explicit operator Double(UDouble value)
   {
      return value.number;
   }

   public static implicit operator Single(UDouble value)
   {
      if (value.number > (double) Single.MaxValue)
         throw new InvalidCastException("A UDouble value is out of range of the Single type.");

      return (float) value.number;
   }

   public static explicit operator UDouble(double value)
   {
      if (value < 0)
         throw new InvalidCastException("A negative value cannot be converted to a UDouble.");

      return new UDouble(value);
   }

   public static implicit operator UDouble(float value)
   {
      if (value < 0)
         throw new InvalidCastException("A negative value cannot be converted to a UDouble.");

      return new UDouble(value);
   }

   public static Double ToDouble(UDouble value)
   {
      return (Double) value;
   }

   public static float ToSingle(UDouble value)
   {
      return (float) value;
   }

   public static UDouble FromDouble(double value)
   {
      return new UDouble(value);
   }

   public static UDouble FromSingle(float value)
   {
      return new UDouble(value);
   }
}
Public Structure UDouble
    Private number As Double

    Public Sub New(value As Double)
        If value < 0 Then
            Throw New InvalidCastException("A negative value cannot be converted to a UDouble.")
        End If
        number = value
    End Sub

    Public Sub New(value As Single)
        If value < 0 Then
            Throw New InvalidCastException("A negative value cannot be converted to a UDouble.")
        End If
        number = value
    End Sub

    Public Shared ReadOnly MinValue As UDouble = CType(0.0, UDouble)
    Public Shared ReadOnly MaxValue As UDouble = Double.MaxValue

    Public Shared Widening Operator CType(value As UDouble) As Double
        Return value.number
    End Operator

    Public Shared Narrowing Operator CType(value As UDouble) As Single
        If value.number > CDbl(Single.MaxValue) Then
            Throw New InvalidCastException("A UDouble value is out of range of the Single type.")
        End If
        Return CSng(value.number)
    End Operator

    Public Shared Narrowing Operator CType(value As Double) As UDouble
        If value < 0 Then
            Throw New InvalidCastException("A negative value cannot be converted to a UDouble.")
        End If
        Return New UDouble(value)
    End Operator

    Public Shared Narrowing Operator CType(value As Single) As UDouble
        If value < 0 Then
            Throw New InvalidCastException("A negative value cannot be converted to a UDouble.")
        End If
        Return New UDouble(value)
    End Operator

    Public Shared Function ToDouble(value As UDouble) As Double
        Return CType(value, Double)
    End Function

    Public Shared Function ToSingle(value As UDouble) As Single
        Return CType(value, Single)
    End Function

    Public Shared Function FromDouble(value As Double) As UDouble
        Return New UDouble(value)
    End Function

    Public Shared Function FromSingle(value As Single) As UDouble
        Return New UDouble(value)
    End Function
End Structure

Diziler

CLS uyumlu diziler aşağıdaki kurallara uyar:

  • Bir dizinin tüm boyutları sıfırın alt sınırına sahip olmalıdır. Aşağıdaki örnek, alt sınırı bir olan CLS uyumlu olmayan bir dizi oluşturur. CLSCompliantAttribute özniteliğinin bulunmasına rağmen, derleyici Numbers.GetTenPrimes yöntemi tarafından döndürülen dizinin CLS uyumlu olmadığını algılamaz.

    [assembly: CLSCompliant(true)]
    
    public class Numbers
    {
       public static Array GetTenPrimes()
       {
          Array arr = Array.CreateInstance(typeof(Int32), new int[] {10}, new int[] {1});
          arr.SetValue(1, 1);
          arr.SetValue(2, 2);
          arr.SetValue(3, 3);
          arr.SetValue(5, 4);
          arr.SetValue(7, 5);
          arr.SetValue(11, 6);
          arr.SetValue(13, 7);
          arr.SetValue(17, 8);
          arr.SetValue(19, 9);
          arr.SetValue(23, 10);
    
          return arr;
       }
    }
    
    <Assembly: CLSCompliant(True)>
    
    Public Class Numbers
        Public Shared Function GetTenPrimes() As Array
            Dim arr As Array = Array.CreateInstance(GetType(Int32), {10}, {1})
            arr.SetValue(1, 1)
            arr.SetValue(2, 2)
            arr.SetValue(3, 3)
            arr.SetValue(5, 4)
            arr.SetValue(7, 5)
            arr.SetValue(11, 6)
            arr.SetValue(13, 7)
            arr.SetValue(17, 8)
            arr.SetValue(19, 9)
            arr.SetValue(23, 10)
    
            Return arr
        End Function
    End Class
    
  • Tüm dizi öğeleri CLS uyumlu türlerden oluşmalıdır. Aşağıdaki örnek, CLS uyumlu olmayan diziler döndüren iki yöntemi tanımlar. birincisi, UInt32 değer dizisini döndürür. İkincisi, Object ve Int32 değerleri içeren bir UInt32 dizisi döndürür. Derleyici, ilk diziyi UInt32 türü nedeniyle uyumsuz olarak tanımlasa da, ikinci dizinin CLS uyumlu olmayan öğeler içerdiğini algılayamaz.

    using System;
    
    [assembly: CLSCompliant(true)]
    
    public class Numbers
    {
       public static UInt32[] GetTenPrimes()
       {
          uint[] arr = { 1u, 2u, 3u, 5u, 7u, 11u, 13u, 17u, 19u };
          return arr;
       }
    
       public static Object[] GetFivePrimes()
       {
          Object[] arr = { 1, 2, 3, 5u, 7u };
          return arr;
       }
    }
    // Compilation produces a compiler warning like the following:
    //    Array2.cs(8,27): warning CS3002: Return type of 'Numbers.GetTenPrimes()' is not
    //            CLS-compliant
    
    <Assembly: CLSCompliant(True)>
    
    Public Class Numbers
        Public Shared Function GetTenPrimes() As UInt32()
            Return {1ui, 2ui, 3ui, 5ui, 7ui, 11ui, 13ui, 17ui, 19ui}
        End Function
    
        Public Shared Function GetFivePrimes() As Object()
            Dim arr() As Object = {1, 2, 3, 5ui, 7ui}
            Return arr
        End Function
    End Class
    ' Compilation produces a compiler warning like the following:
    '    warning BC40027: Return type of function 'GetTenPrimes' is not CLS-compliant.
    '    
    '       Public Shared Function GetTenPrimes() As UInt32()
    '                              ~~~~~~~~~~~~
    
  • Dizi parametrelerine sahip yöntemler için aşırı yükleme çözümlemesi, dizi olmalarına ve öğe türlerine dayalıdır. Bu nedenle, aşırı yüklenmiş bir GetSquares yönteminin aşağıdaki tanımı CLS uyumludur.

    using System;
    using System.Numerics;
    
    [assembly: CLSCompliant(true)]
    
    public class Numbers
    {
       public static byte[] GetSquares(byte[] numbers)
       {
          byte[] numbersOut = new byte[numbers.Length];
          for (int ctr = 0; ctr < numbers.Length; ctr++) {
             int square = ((int) numbers[ctr]) * ((int) numbers[ctr]);
             if (square <= Byte.MaxValue)
                numbersOut[ctr] = (byte) square;
             // If there's an overflow, assign MaxValue to the corresponding
             // element.
             else
                numbersOut[ctr] = Byte.MaxValue;
          }
          return numbersOut;
       }
    
       public static BigInteger[] GetSquares(BigInteger[] numbers)
       {
          BigInteger[] numbersOut = new BigInteger[numbers.Length];
          for (int ctr = 0; ctr < numbers.Length; ctr++)
             numbersOut[ctr] = numbers[ctr] * numbers[ctr];
    
          return numbersOut;
       }
    }
    
    Imports System.Numerics
    
    <Assembly: CLSCompliant(True)>
    
    Public Module Numbers
        Public Function GetSquares(numbers As Byte()) As Byte()
            Dim numbersOut(numbers.Length - 1) As Byte
            For ctr As Integer = 0 To numbers.Length - 1
                Dim square As Integer = (CInt(numbers(ctr)) * CInt(numbers(ctr)))
                If square <= Byte.MaxValue Then
                    numbersOut(ctr) = CByte(square)
                    ' If there's an overflow, assign MaxValue to the corresponding 
                    ' element.
                Else
                    numbersOut(ctr) = Byte.MaxValue
                End If
            Next
            Return numbersOut
        End Function
    
        Public Function GetSquares(numbers As BigInteger()) As BigInteger()
            Dim numbersOut(numbers.Length - 1) As BigInteger
            For ctr As Integer = 0 To numbers.Length - 1
                numbersOut(ctr) = numbers(ctr) * numbers(ctr)
            Next
            Return numbersOut
        End Function
    End Module
    

Arayüzler

CLS uyumlu arabirimler özellikleri, olayları ve sanal yöntemleri (uygulamasız yöntemler) tanımlayabilir. CLS uyumlu bir arabirim aşağıdakilerden herhangi birine sahip olamaz:

  • Statik yöntemler veya statik alanlar. Bir arabirimde statik üye tanımlarsanız hem C# hem de Visual Basic derleyicileri derleyici hataları oluşturur.

  • Alanları. Bir arabirimde alan tanımlarsanız hem C# hem de Visual Basic derleyicileri derleyici hataları oluşturur.

  • CLS uyumlu olmayan yöntemler. Örneğin, aşağıdaki arabirim tanımı CLS uyumlu değil olarak işaretlenmiş INumber.GetUnsignedyöntemini içerir. Bu örnek bir derleyici uyarısı oluşturur.

    using System;
    
    [assembly:CLSCompliant(true)]
    
    public interface INumber
    {
       int Length();
       [CLSCompliant(false)] ulong GetUnsigned();
    }
    // Attempting to compile the example displays output like the following:
    //    Interface2.cs(8,32): warning CS3010: 'INumber.GetUnsigned()': CLS-compliant interfaces
    //            must have only CLS-compliant members
    
    <Assembly: CLSCompliant(True)>
    
    Public Interface INumber
        Function Length As Integer
    
        <CLSCompliant(False)> Function GetUnsigned As ULong
    End Interface
    ' Attempting to compile the example displays output like the following:
    '    Interface2.vb(9) : warning BC40033: Non CLS-compliant 'function' is not allowed in a 
    '    CLS-compliant interface.
    '    
    '       <CLSCompliant(False)> Function GetUnsigned As ULong
    '                                      ~~~~~~~~~~~
    

    Bu kural nedeniyle, CLS uyumlu türlerin CLS uyumlu olmayan üyeleri uygulamaları zorunlu değildir. CLS uyumlu bir çerçeve CLS uyumlu olmayan bir arabirim uygulayan bir sınıfı kullanıma sunarsa, CLS uyumlu olmayan tüm üyelerin somut uygulamalarını da sağlamalıdır.

CLS uyumlu dil derleyicileri, bir sınıfın birden çok arabirimde aynı ada ve imzaya sahip üyelerin ayrı uygulamalarını sağlamasına da izin vermelidir. Hem C# hem de Visual Basic, aynı adlı yöntemlerin farklı uygulamalarını sağlamak için açık arabirim uygulamaları destekler. Visual Basic, belirli bir üyenin hangi arabirimi ve üyeyi uyguladığını açıkça belirlemenizi sağlayan Implements anahtar sözcüğünü de destekler. Aşağıdaki örnek, Temperature ve ICelsius arabirimlerini açık arabirim uygulamaları olarak uygulayan bir IFahrenheit sınıfı tanımlayarak bu senaryoyu göstermektedir.

using System;

[assembly: CLSCompliant(true)]

public interface IFahrenheit
{
   decimal GetTemperature();
}

public interface ICelsius
{
   decimal GetTemperature();
}

public class Temperature : ICelsius, IFahrenheit
{
   private decimal _value;

   public Temperature(decimal value)
   {
      // We assume that this is the Celsius value.
      _value = value;
   }

   decimal IFahrenheit.GetTemperature()
   {
      return _value * 9 / 5 + 32;
   }

   decimal ICelsius.GetTemperature()
   {
      return _value;
   }
}
public class Example
{
   public static void Main()
   {
      Temperature temp = new Temperature(100.0m);
      ICelsius cTemp = temp;
      IFahrenheit fTemp = temp;
      Console.WriteLine($"Temperature in Celsius: {cTemp.GetTemperature()} degrees");
      Console.WriteLine($"Temperature in Fahrenheit: {fTemp.GetTemperature()} degrees");
   }
}
// The example displays the following output:
//       Temperature in Celsius: 100.0 degrees
//       Temperature in Fahrenheit: 212.0 degrees
<Assembly: CLSCompliant(True)>

Public Interface IFahrenheit
    Function GetTemperature() As Decimal
End Interface

Public Interface ICelsius
    Function GetTemperature() As Decimal
End Interface

Public Class Temperature : Implements ICelsius, IFahrenheit
    Private _value As Decimal

    Public Sub New(value As Decimal)
        ' We assume that this is the Celsius value.
        _value = value
    End Sub

    Public Function GetFahrenheit() As Decimal _
           Implements IFahrenheit.GetTemperature
        Return _value * 9 / 5 + 32
    End Function

    Public Function GetCelsius() As Decimal _
           Implements ICelsius.GetTemperature
        Return _value
    End Function
End Class

Module Example
    Public Sub Main()
        Dim temp As New Temperature(100.0d)
        Console.WriteLine("Temperature in Celsius: {0} degrees",
                          temp.GetCelsius())
        Console.WriteLine("Temperature in Fahrenheit: {0} degrees",
                          temp.GetFahrenheit())
    End Sub
End Module
' The example displays the following output:
'       Temperature in Celsius: 100.0 degrees
'       Temperature in Fahrenheit: 212.0 degrees

Numaralandırma

CLS uyumlu numaralandırmaların şu kurallara uyması gerekir:

  • Numaralandırmanın temel türü, iç CLS uyumlu bir tamsayı (Byte, Int16, Int32veya Int64) olmalıdır. Örneğin, aşağıdaki kod temel türü UInt32 olan bir numaralandırma tanımlamaya çalışır ve derleyici uyarısı oluşturur.

    using System;
    
    [assembly: CLSCompliant(true)]
    
    public enum Size : uint {
       Unspecified = 0,
       XSmall = 1,
       Small = 2,
       Medium = 3,
       Large = 4,
       XLarge = 5
    };
    
    public class Clothing
    {
       public string Name;
       public string Type;
       public string Size;
    }
    // The attempt to compile the example displays a compiler warning like the following:
    //    Enum3.cs(6,13): warning CS3009: 'Size': base type 'uint' is not CLS-compliant
    
    <Assembly: CLSCompliant(True)>
    
    Public Enum Size As UInt32
        Unspecified = 0
        XSmall = 1
        Small = 2
        Medium = 3
        Large = 4
        XLarge = 5
    End Enum
    
    Public Class Clothing
        Public Name As String
        Public Type As String
        Public Size As Size
    End Class
    ' The attempt to compile the example displays a compiler warning like the following:
    '    Enum3.vb(6) : warning BC40032: Underlying type 'UInt32' of Enum is not CLS-compliant.
    '    
    '    Public Enum Size As UInt32
    '                ~~~~
    
  • Numaralandırma türü, Value__ özniteliğiyle işaretlenmiş FieldAttributes.RTSpecialName adlı tek bir örnek alanına sahip olmalıdır. Bu, alan değerine örtük olarak atıfta bulunma olanağı sağlar.

  • Bir numaralandırma, türleri kendi numaralandırma türüyle eşleşen harfi statik alanlar içerir. Örneğin, State ve State.Ondeğerleriyle bir State.Off numaralandırması tanımlarsanız, State.On ve State.Off türü Stateolan sabit statik alanlardır.

  • İki tür numaralandırma vardır:

    • Birbirini dışlayan, adlandırılmış tamsayı değerleri kümesini temsil eden bir numaralandırma. Bu tür bir sabit listesi, System.FlagsAttribute özel özniteliğinin olmamasıyla gösterilir.

    • Adsız bir değer oluşturmak için birleştirilebilen bit bayrakları kümesini temsil eden bir numaralandırma. Bu tür bir numaralandırma, System.FlagsAttribute özel özniteliğinin varlığıyla gösterilir.

    Daha fazla bilgi için Enum yapısının belgelerine bakın.

  • Bir sabit listesi değeri, belirtilen değerlerin aralığıyla sınırlı değildir. Başka bir deyişle, bir numaralandırmadaki değer aralığı, temel alınan değerin aralığıdır. Belirtilen değerin bir sabit listesi üyesi olup olmadığını belirlemek için Enum.IsDefined yöntemini kullanabilirsiniz.

Genel anlamda tip üyeleri

Ortak Dil Belirtimi, tüm alanlara ve yöntemlere belirli bir sınıfın üyesi olarak erişmeyi gerektirir. Bu nedenle, genel statik alanlar ve yöntemler (bir tür dışında tanımlanan statik alanlar veya yöntemler) CLS uyumlu değildir. Kaynak kodunuza genel bir alan veya yöntem eklemeye çalışırsanız, hem C# hem de Visual Basic derleyicileri derleyici hatası oluşturur.

Ortak Dil Belirtimi yalnızca standart yönetilen çağrı kuralını destekler. Yönetilmeyen çağrı kurallarını ve varargs anahtar sözcüğüyle işaretlenmiş değişken bağımsız değişken listelerine sahip yöntemleri desteklemez. Standart yönetilen çağrı kuralıyla uyumlu değişken bağımsız değişken listeleri için ParamArrayAttribute özniteliğini veya C# dilinde params anahtar sözcüğü ve Visual Basic'teki ParamArray anahtar sözcüğü gibi tek tek dilin uygulamasını kullanın.

Üye erişilebilirliği

Devralınan bir üyenin geçersiz kılınması, o üyenin erişilebilirliğini değiştiremez. Örneğin, bir temel sınıftaki ortak yöntem, türetilmiş bir sınıftaki özel bir yöntem tarafından geçersiz kılınamaz. Bir istisna vardır: farklı bir derlemedeki bir türün geçersiz kıldığı bir derlemede bulunan protected internal (C#'de) veya Protected Friend (Visual Basic'te) üyesi. Bu durumda geçersiz kılmanın erişilebilirliği Protectedolur.

Aşağıdaki örnek, CLSCompliantAttribute özniteliği trueolarak ayarlandığında ve Humantüretilmiş bir sınıf olan Animal, Species özelliğinin erişilebilirliğini genelden özele değiştirmeye çalıştığında oluşturulan hatayı gösterir. Erişilebilirliği herkese açık olarak değiştirildiğinde örnek başarıyla derlenir.

using System;

[assembly: CLSCompliant(true)]

public class Animal
{
   private string _species;

   public Animal(string species)
   {
      _species = species;
   }

   public virtual string Species
   {
      get { return _species; }
   }

   public override string ToString()
   {
      return _species;
   }
}

public class Human : Animal
{
   private string _name;

   public Human(string name) : base("Homo Sapiens")
   {
      _name = name;
   }

   public string Name
   {
      get { return _name; }
   }

   private override string Species
   {
      get { return base.Species; }
   }

   public override string ToString()
   {
      return _name;
   }
}

public class Example
{
   public static void Main()
   {
      Human p = new Human("John");
      Console.WriteLine(p.Species);
      Console.WriteLine(p.ToString());
   }
}
// The example displays the following output:
//    error CS0621: 'Human.Species': virtual or abstract members cannot be private
<Assembly: CLSCompliant(True)>

Public Class Animal
    Private _species As String

    Public Sub New(species As String)
        _species = species
    End Sub

    Public Overridable ReadOnly Property Species As String
        Get
            Return _species
        End Get
    End Property

    Public Overrides Function ToString() As String
        Return _species
    End Function
End Class

Public Class Human : Inherits Animal
    Private _name As String

    Public Sub New(name As String)
        MyBase.New("Homo Sapiens")
        _name = name
    End Sub

    Public ReadOnly Property Name As String
        Get
            Return _name
        End Get
    End Property

    Private Overrides ReadOnly Property Species As String
        Get
            Return MyBase.Species
        End Get
    End Property

    Public Overrides Function ToString() As String
        Return _name
    End Function
End Class

Public Module Example
    Public Sub Main()
        Dim p As New Human("John")
        Console.WriteLine(p.Species)
        Console.WriteLine(p.ToString())
    End Sub
End Module
' The example displays the following output:
'     'Private Overrides ReadOnly Property Species As String' cannot override 
'     'Public Overridable ReadOnly Property Species As String' because
'      they have different access levels.
' 
'         Private Overrides ReadOnly Property Species As String

Bir üyenin imzasındaki türler, üyenin erişilebilir olduğu her durumda erişilebilir olmalıdır. Örneğin, bu, bir genel üyenin türü özel, korumalı veya iç olan bir parametre içermemesi gerektiği anlamına gelir. Aşağıdaki örnek, bir StringWrapper sınıf oluşturucusunun, bir dize değerinin nasıl sarmalanacağını belirleyen iç StringOperationType numaralandırma değerini açığa çıkardığında ortaya çıkan derleyici hatasını göstermektedir.

using System;
using System.Text;

public class StringWrapper
{
   string internalString;
   StringBuilder internalSB = null;
   bool useSB = false;

   public StringWrapper(StringOperationType type)
   {
      if (type == StringOperationType.Normal) {
         useSB = false;
      }
      else {
         useSB = true;
         internalSB = new StringBuilder();
      }
   }

   // The remaining source code...
}

internal enum StringOperationType { Normal, Dynamic }
// The attempt to compile the example displays the following output:
//    error CS0051: Inconsistent accessibility: parameter type
//            'StringOperationType' is less accessible than method
//            'StringWrapper.StringWrapper(StringOperationType)'
Imports System.Text

<Assembly: CLSCompliant(True)>

Public Class StringWrapper

    Dim internalString As String
    Dim internalSB As StringBuilder = Nothing
    Dim useSB As Boolean = False

    Public Sub New(type As StringOperationType)
        If type = StringOperationType.Normal Then
            useSB = False
        Else
            internalSB = New StringBuilder()
            useSB = True
        End If
    End Sub

    ' The remaining source code...
End Class

Friend Enum StringOperationType As Integer
    Normal = 0
    Dynamic = 1
End Enum
' The attempt to compile the example displays the following output:
'    error BC30909: 'type' cannot expose type 'StringOperationType'
'     outside the project through class 'StringWrapper'.
'    
'       Public Sub New(type As StringOperationType)
'                              ~~~~~~~~~~~~~~~~~~~

Genel türler ve üyeler

İç içe türlerin her zaman en az kendisini kapsayan tür kadar genel parametresi vardır. Bunlar, kapsayan türde bulunan genel parametrelerin konumlarına karşılık gelir. Genel tür, yeni genel parametreler de içerebilir.

İç içe türler içeren bir türün genel tür parametreleri ile iç içe türler arasındaki ilişki, tek tek dillerin söz dizimi tarafından gizlenebilir. Aşağıdaki örnekte, genel tür Outer<T>Inner1A ve Inner1B<U>olmak üzere iki iç içe sınıf içerir. her sınıfın ToString'den devraldığı Object.ToString() yöntemine çağrılar, her iç içe sınıfın kendi içeren sınıfının tür parametrelerini içerdiğini gösterir.

using System;

[assembly:CLSCompliant(true)]

public class Outer<T>
{
   T value;

   public Outer(T value)
   {
      this.value = value;
   }

   public class Inner1A : Outer<T>
   {
      public Inner1A(T value) : base(value)
      {  }
   }

   public class Inner1B<U> : Outer<T>
   {
      U value2;

      public Inner1B(T value1, U value2) : base(value1)
      {
         this.value2 = value2;
      }
   }
}

public class Example
{
   public static void Main()
   {
      var inst1 = new Outer<String>("This");
      Console.WriteLine(inst1);

      var inst2 = new Outer<String>.Inner1A("Another");
      Console.WriteLine(inst2);

      var inst3 = new Outer<String>.Inner1B<int>("That", 2);
      Console.WriteLine(inst3);
   }
}
// The example displays the following output:
//       Outer`1[System.String]
//       Outer`1+Inner1A[System.String]
//       Outer`1+Inner1B`1[System.String,System.Int32]
<Assembly: CLSCompliant(True)>

Public Class Outer(Of T)
    Dim value As T

    Public Sub New(value As T)
        Me.value = value
    End Sub

    Public Class Inner1A : Inherits Outer(Of T)
        Public Sub New(value As T)
            MyBase.New(value)
        End Sub
    End Class

    Public Class Inner1B(Of U) : Inherits Outer(Of T)
        Dim value2 As U

        Public Sub New(value1 As T, value2 As U)
            MyBase.New(value1)
            Me.value2 = value2
        End Sub
    End Class
End Class

Public Module Example
    Public Sub Main()
        Dim inst1 As New Outer(Of String)("This")
        Console.WriteLine(inst1)

        Dim inst2 As New Outer(Of String).Inner1A("Another")
        Console.WriteLine(inst2)

        Dim inst3 As New Outer(Of String).Inner1B(Of Integer)("That", 2)
        Console.WriteLine(inst3)
    End Sub
End Module
' The example displays the following output:
'       Outer`1[System.String]
'       Outer`1+Inner1A[System.String]
'       Outer`1+Inner1B`1[System.String,System.Int32]

Genel tür adları ad`nbiçiminde kodlanır; burada ad tür adıdır, ` bir karakter sabitidir ve n tür üzerinde bildirilen parametre sayısıdır veya iç içe geçmiş genel türler için yeni tanıtılan tür parametrelerinin sayısıdır. Genel tür adlarının bu kodlanması, bir kitaplıktaki CLS-uyumlu genel türlere erişmek için reflection kullanan geliştiriciler için özellikle ilgilidir.

Kısıtlamalar genel bir türe uygulanırsa, kısıtlama olarak kullanılan tüm türlerin de CLS uyumlu olması gerekir. Aşağıdaki örnek, CLS uyumlu olmayan BaseClass adlı bir sınıfı ve tür parametresinin BaseCollectiontüretmesi gereken BaseClass adlı genel bir sınıfı tanımlar. Ancak BaseClass CLS uyumlu olmadığından, derleyici bir uyarı yayar.

using System;

[assembly:CLSCompliant(true)]

[CLSCompliant(false)] public class BaseClass
{}

public class BaseCollection<T> where T : BaseClass
{}
// Attempting to compile the example displays the following output:
//    warning CS3024: Constraint type 'BaseClass' is not CLS-compliant
<Assembly: CLSCompliant(True)>

<CLSCompliant(False)> Public Class BaseClass
End Class


Public Class BaseCollection(Of T As BaseClass)
End Class
' Attempting to compile the example displays the following output:
'    warning BC40040: Generic parameter constraint type 'BaseClass' is not 
'    CLS-compliant.
'    
'    Public Class BaseCollection(Of T As BaseClass)
'                                        ~~~~~~~~~

Genel bir tür genel bir temel türden türetilirse, temel türdeki kısıtlamaların da karşılandığını garanti edebilmesi için tüm kısıtlamaları yeniden eklemesi gerekir. Aşağıdaki örnek, herhangi bir sayısal türü temsil eden bir Number<T> tanımlar. Ayrıca kayan nokta değerini temsil eden bir FloatingPoint<T> sınıfı tanımlar. Ancak, kaynak kod Number<T>için FloatingPoint<T> kısıtlaması uygulamadığından (bu T bir değer türü olmalıdır) derlenemiyor.

using System;

[assembly:CLSCompliant(true)]

public class Number<T> where T : struct
{
   // use Double as the underlying type, since its range is a superset of
   // the ranges of all numeric types except BigInteger.
   protected double number;

   public Number(T value)
   {
      try {
         this.number = Convert.ToDouble(value);
      }
      catch (OverflowException e) {
         throw new ArgumentException("value is too large.", e);
      }
      catch (InvalidCastException e) {
         throw new ArgumentException("The value parameter is not numeric.", e);
      }
   }

   public T Add(T value)
   {
      return (T) Convert.ChangeType(number + Convert.ToDouble(value), typeof(T));
   }

   public T Subtract(T value)
   {
      return (T) Convert.ChangeType(number - Convert.ToDouble(value), typeof(T));
   }
}

public class FloatingPoint<T> : Number<T>
{
   public FloatingPoint(T number) : base(number)
   {
      if (typeof(float) == number.GetType() ||
          typeof(double) == number.GetType() ||
          typeof(decimal) == number.GetType())
         this.number = Convert.ToDouble(number);
      else
         throw new ArgumentException("The number parameter is not a floating-point number.");
   }
}
// The attempt to compile the example displays the following output:
//       error CS0453: The type 'T' must be a non-nullable value type in
//               order to use it as parameter 'T' in the generic type or method 'Number<T>'
<Assembly: CLSCompliant(True)>

Public Class Number(Of T As Structure)
    ' Use Double as the underlying type, since its range is a superset of
    ' the ranges of all numeric types except BigInteger.
    Protected number As Double

    Public Sub New(value As T)
        Try
            Me.number = Convert.ToDouble(value)
        Catch e As OverflowException
            Throw New ArgumentException("value is too large.", e)
        Catch e As InvalidCastException
            Throw New ArgumentException("The value parameter is not numeric.", e)
        End Try
    End Sub

    Public Function Add(value As T) As T
        Return CType(Convert.ChangeType(number + Convert.ToDouble(value), GetType(T)), T)
    End Function

    Public Function Subtract(value As T) As T
        Return CType(Convert.ChangeType(number - Convert.ToDouble(value), GetType(T)), T)
    End Function
End Class

Public Class FloatingPoint(Of T) : Inherits Number(Of T)
    Public Sub New(number As T)
        MyBase.New(number)
        If TypeOf number Is Single Or
                 TypeOf number Is Double Or
                 TypeOf number Is Decimal Then
            Me.number = Convert.ToDouble(number)
        Else
            throw new ArgumentException("The number parameter is not a floating-point number.")
        End If
    End Sub
End Class
' The attempt to compile the example displays the following output:
'    error BC32105: Type argument 'T' does not satisfy the 'Structure'
'    constraint for type parameter 'T'.
'    
'    Public Class FloatingPoint(Of T) : Inherits Number(Of T)
'                                                          ~

Kısıtlama FloatingPoint<T> sınıfına eklenirse örnek başarıyla derleniyor.

using System;

[assembly:CLSCompliant(true)]

public class Number<T> where T : struct
{
   // use Double as the underlying type, since its range is a superset of
   // the ranges of all numeric types except BigInteger.
   protected double number;

   public Number(T value)
   {
      try {
         this.number = Convert.ToDouble(value);
      }
      catch (OverflowException e) {
         throw new ArgumentException("value is too large.", e);
      }
      catch (InvalidCastException e) {
         throw new ArgumentException("The value parameter is not numeric.", e);
      }
   }

   public T Add(T value)
   {
      return (T) Convert.ChangeType(number + Convert.ToDouble(value), typeof(T));
   }

   public T Subtract(T value)
   {
      return (T) Convert.ChangeType(number - Convert.ToDouble(value), typeof(T));
   }
}

public class FloatingPoint<T> : Number<T> where T : struct
{
   public FloatingPoint(T number) : base(number)
   {
      if (typeof(float) == number.GetType() ||
          typeof(double) == number.GetType() ||
          typeof(decimal) == number.GetType())
         this.number = Convert.ToDouble(number);
      else
         throw new ArgumentException("The number parameter is not a floating-point number.");
   }
}
<Assembly: CLSCompliant(True)>

Public Class Number(Of T As Structure)
    ' Use Double as the underlying type, since its range is a superset of
    ' the ranges of all numeric types except BigInteger.
    Protected number As Double

    Public Sub New(value As T)
        Try
            Me.number = Convert.ToDouble(value)
        Catch e As OverflowException
            Throw New ArgumentException("value is too large.", e)
        Catch e As InvalidCastException
            Throw New ArgumentException("The value parameter is not numeric.", e)
        End Try
    End Sub

    Public Function Add(value As T) As T
        Return CType(Convert.ChangeType(number + Convert.ToDouble(value), GetType(T)), T)
    End Function

    Public Function Subtract(value As T) As T
        Return CType(Convert.ChangeType(number - Convert.ToDouble(value), GetType(T)), T)
    End Function
End Class

Public Class FloatingPoint(Of T As Structure) : Inherits Number(Of T)
    Public Sub New(number As T)
        MyBase.New(number)
        If TypeOf number Is Single Or
                 TypeOf number Is Double Or
                 TypeOf number Is Decimal Then
            Me.number = Convert.ToDouble(number)
        Else
            throw new ArgumentException("The number parameter is not a floating-point number.")
        End If
    End Sub
End Class

Ortak Dil Belirtimi, iç içe türler ve korumalı üyeler için örnek başına muhafazakar bir model uygular. Açık genel türler, iç içe, korumalı bir genel türün belirli bir örneğini içeren imzalara sahip alanları veya üyeleri kullanıma sunamaz. Genel bir temel sınıfın veya arabirimin belirli bir örneğini genişleten genel olmayan türler, iç içe, korumalı bir genel türün farklı bir örneğini içeren imzalara sahip alanları veya üyeleri kullanıma sunamaz.

Aşağıdaki örnek genel bir tür, C1<T> (veya Visual Basic'te C1(Of T)) ve korumalı bir sınıf, C1<T>.N (veya Visual Basic'te C1(Of T).N) tanımlar. C1<T> M1 ve M2adlı iki yöntemi vardır. Ancak M1, C1C1<int>.NTC1(Of Integer).N (veya <) öğesinden > (veya C1(Of T)) nesnesi döndürmeye çalıştığından CLS uyumlu değildir. C2ikinci bir sınıf, C1<long> (veya C1(Of Long)) öğesinden türetilir. M3 ve M4adlı iki yöntemi vardır. M3, C1<int>.Nalt sınıfından bir C1(Of Integer).N (veya C1<long>) nesnesi döndürmeye çalıştığından CLS uyumlu değildir. Dil derleyicileri daha da kısıtlayıcı olabilir. Bu örnekte Visual Basic, M4derlemeye çalıştığında bir hata görüntüler.

using System;

[assembly:CLSCompliant(true)]

public class C1<T>
{
   protected class N { }

   protected void M1(C1<int>.N n) { } // Not CLS-compliant - C1<int>.N not
                                      // accessible from within C1<T> in all
                                      // languages
   protected void M2(C1<T>.N n) { }   // CLS-compliant – C1<T>.N accessible
                                      // inside C1<T>
}

public class C2 : C1<long>
{
   protected void M3(C1<int>.N n) { }  // Not CLS-compliant – C1<int>.N is not
                                       // accessible in C2 (extends C1<long>)

   protected void M4(C1<long>.N n) { } // CLS-compliant, C1<long>.N is
                                       // accessible in C2 (extends C1<long>)
}
// Attempting to compile the example displays output like the following:
//       Generics4.cs(9,22): warning CS3001: Argument type 'C1<int>.N' is not CLS-compliant
//       Generics4.cs(18,22): warning CS3001: Argument type 'C1<int>.N' is not CLS-compliant
<Assembly: CLSCompliant(True)>

Public Class C1(Of T)
    Protected Class N
    End Class

    Protected Sub M1(n As C1(Of Integer).N)   ' Not CLS-compliant - C1<int>.N not
        ' accessible from within C1(Of T) in all
    End Sub                                   ' languages


    Protected Sub M2(n As C1(Of T).N)     ' CLS-compliant – C1(Of T).N accessible
    End Sub                               ' inside C1(Of T)
End Class

Public Class C2 : Inherits C1(Of Long)
    Protected Sub M3(n As C1(Of Integer).N)   ' Not CLS-compliant – C1(Of Integer).N is not
    End Sub                                   ' accessible in C2 (extends C1(Of Long))

    Protected Sub M4(n As C1(Of Long).N)
    End Sub
End Class
' Attempting to compile the example displays output like the following:
'    error BC30508: 'n' cannot expose type 'C1(Of Integer).N' in namespace 
'    '<Default>' through class 'C1'.
'    
'       Protected Sub M1(n As C1(Of Integer).N)   ' Not CLS-compliant - C1<int>.N not
'                             ~~~~~~~~~~~~~~~~
'    error BC30389: 'C1(Of T).N' is not accessible in this context because 
'    it is 'Protected'.
'    
'       Protected Sub M3(n As C1(Of Integer).N)   ' Not CLS-compliant - C1(Of Integer).N is not
'    
'                             ~~~~~~~~~~~~~~~~
'    
'    error BC30389: 'C1(Of T).N' is not accessible in this context because it is 'Protected'.
'    
'       Protected Sub M4(n As C1(Of Long).N)  
'                             ~~~~~~~~~~~~~

Kurucular

CLS uyumlu sınıflardaki ve yapılardaki oluşturucuların şu kurallara uyması gerekir:

  • Türetilmiş bir sınıfın oluşturucusunun devralınan örnek verilerine erişmeden önce temel sınıfının örnek oluşturucusunu çağırması gerekir. Bu gereksinimin nedeni, türetilmiş sınıfların temel sınıf oluşturucularını devralmamasıdır. Bu kural, doğrudan devralmayı desteklemeyen yapılar için geçerli değildir.

    Derleyiciler genellikle aşağıdaki örnekte gösterildiği gibi bu kuralı CLS uyumluluğundan bağımsız olarak zorlar. bir Doctor sınıfından türetilen bir Person sınıfı oluşturur, ancak Doctor sınıfı devralınan örnek alanlarını başlatmak için Person sınıf oluşturucuyu çağıramıyor.

    using System;
    
    [assembly: CLSCompliant(true)]
    
    public class Person
    {
       private string fName, lName, _id;
    
       public Person(string firstName, string lastName, string id)
       {
          if (String.IsNullOrEmpty(firstName + lastName))
             throw new ArgumentNullException("Either a first name or a last name must be provided.");
    
          fName = firstName;
          lName = lastName;
          _id = id;
       }
    
       public string FirstName
       {
          get { return fName; }
       }
    
       public string LastName
       {
          get { return lName; }
       }
    
       public string Id
       {
          get { return _id; }
       }
    
       public override string ToString()
       {
          return String.Format("{0}{1}{2}", fName,
                               String.IsNullOrEmpty(fName) ?  "" : " ",
                               lName);
       }
    }
    
    public class Doctor : Person
    {
       public Doctor(string firstName, string lastName, string id)
       {
       }
    
       public override string ToString()
       {
          return "Dr. " + base.ToString();
       }
    }
    // Attempting to compile the example displays output like the following:
    //    ctor1.cs(45,11): error CS1729: 'Person' does not contain a constructor that takes 0
    //            arguments
    //    ctor1.cs(10,11): (Location of symbol related to previous error)
    
    <Assembly: CLSCompliant(True)>
    
    Public Class Person
        Private fName, lName, _id As String
    
        Public Sub New(firstName As String, lastName As String, id As String)
            If String.IsNullOrEmpty(firstName + lastName) Then
                Throw New ArgumentNullException("Either a first name or a last name must be provided.")
            End If
    
            fName = firstName
            lName = lastName
            _id = id
        End Sub
    
        Public ReadOnly Property FirstName As String
            Get
                Return fName
            End Get
        End Property
    
        Public ReadOnly Property LastName As String
            Get
                Return lName
            End Get
        End Property
    
        Public ReadOnly Property Id As String
            Get
                Return _id
            End Get
        End Property
    
        Public Overrides Function ToString() As String
            Return String.Format("{0}{1}{2}", fName,
                                 If(String.IsNullOrEmpty(fName), "", " "),
                                 lName)
        End Function
    End Class
    
    Public Class Doctor : Inherits Person
        Public Sub New(firstName As String, lastName As String, id As String)
        End Sub
    
        Public Overrides Function ToString() As String
            Return "Dr. " + MyBase.ToString()
        End Function
    End Class
    ' Attempting to compile the example displays output like the following:
    '    Ctor1.vb(46) : error BC30148: First statement of this 'Sub New' must be a call 
    '    to 'MyBase.New' or 'MyClass.New' because base class 'Person' of 'Doctor' does 
    '    not have an accessible 'Sub New' that can be called with no arguments.
    '    
    '       Public Sub New()
    '                  ~~~
    
  • Nesne oluşturucu, nesne oluşturma dışında çağrılamaz. Ayrıca, bir nesne iki kez başlatılamaz. Örneğin, bu, Object.MemberwiseClone ve seri durumdan çıkarma yöntemlerinin oluşturucuları çağırmaması gerektiği anlamına gelir.

Özellikler

CLS uyumlu türlerdeki özellikler şu kurallara uymalıdır:

  • Bir özelliğin, bir ayarlayıcısı (setter), bir alıcısı (getter) veya her ikisi de olmalıdır. Bir derlemede bunlar özel yöntemler olarak uygulanır, yani bunlar ayrı yöntemler olarak görünür (alıcı get_özellik adı ve ayarlayıcıset_özellik adıdır) derlemenin meta verilerinde SpecialName olarak işaretlenir. C# ve Visual Basic derleyicileri, CLSCompliantAttribute özniteliğini uygulamaya gerek kalmadan bu kuralı otomatik olarak uygular.

  • Bir özelliğin türü, özellik erişimcisinin dönüş türü ve ayarlayıcının son parametresidir. Bu türlerin CLS uyumlu olması gerekir ve bağımsız değişkenler referans yoluyla özelliğe atanamaz (başka bir ifadeyle, yönetilen işaretçiler olamaz).

  • Bir özelliğin hem alıcısı hem de ayarlayıcısı varsa, her ikisi de ya sanal, ya statik ya da örneksel olmalıdır. C# ve Visual Basic derleyicileri, özellik tanımı söz dizimi aracılığıyla bu kuralı otomatik olarak zorlar.

Etkinlikler

Bir olay adı ve türüne göre tanımlanır. Olay tipi, olayı belirtmek için kullanılan bir temsilcidir. Örneğin, AppDomain.AssemblyResolve olayı ResolveEventHandlertüründedir. Olayın kendisine ek olarak, olay adına dayalı adlara sahip üç yöntem, olayın uygulamasını sağlar ve derlemenin meta verilerinde SpecialName olarak işaretlenir:

  • add_ EventNameadlı bir olay işleyicisi ekleme yöntemi. Örneğin, AppDomain.AssemblyResolve olayının olay aboneliği yöntemi add_AssemblyResolveolarak adlandırılır.

  • remove_ EventNameadlı bir olay işleyicisini kaldırma yöntemi. Örneğin, AppDomain.AssemblyResolve olayının kaldırma yöntemi remove_AssemblyResolveolarak adlandırılır.

  • raise_ EventNameadlı olayın oluştuğunu belirten bir yöntem.

Uyarı

Ortak Dil Belirtiminin olaylarla ilgili kurallarının çoğu dil derleyicileri tarafından uygulanır ve bileşen geliştiricileri için saydamdır.

Olayı ekleme, kaldırma ve yükseltme yöntemleri aynı erişilebilirliğe sahip olmalıdır. Bunların tümü statik, örnek veya sanal olmalıdır. Olay ekleme ve kaldırma yöntemleri, türü olay temsilcisi türü olan bir parametreye sahiptir. Ekleme ve kaldırma yöntemlerinin her ikisi de mevcut veya her ikisi de bulunmamalıdır.

Aşağıdaki örnek, iki okuma arasındaki sıcaklık değişikliği bir eşik değerine eşitse veya aştığında Temperature olayı tetikleyen TemperatureChanged adlı CLS uyumlu bir sınıf tanımlar. Temperature sınıfı, olay işleyicilerini seçmeli olarak yürütebilmesi için açıkça bir raise_TemperatureChanged yöntemi tanımlar.

using System;
using System.Collections;
using System.Collections.Generic;

[assembly: CLSCompliant(true)]

public class TemperatureChangedEventArgs : EventArgs
{
   private Decimal originalTemp;
   private Decimal newTemp;
   private DateTimeOffset when;

   public TemperatureChangedEventArgs(Decimal original, Decimal @new, DateTimeOffset time)
   {
      originalTemp = original;
      newTemp = @new;
      when = time;
   }

   public Decimal OldTemperature
   {
      get { return originalTemp; }
   }

   public Decimal CurrentTemperature
   {
      get { return newTemp; }
   }

   public DateTimeOffset Time
   {
      get { return when; }
   }
}

public delegate void TemperatureChanged(Object sender, TemperatureChangedEventArgs e);

public class Temperature
{
   private struct TemperatureInfo
   {
      public Decimal Temperature;
      public DateTimeOffset Recorded;
   }

   public event TemperatureChanged TemperatureChanged;

   private Decimal previous;
   private Decimal current;
   private Decimal tolerance;
   private List<TemperatureInfo> tis = new List<TemperatureInfo>();

   public Temperature(Decimal temperature, Decimal tolerance)
   {
      current = temperature;
      TemperatureInfo ti = new TemperatureInfo();
      ti.Temperature = temperature;
      tis.Add(ti);
      ti.Recorded = DateTimeOffset.UtcNow;
      this.tolerance = tolerance;
   }

   public Decimal CurrentTemperature
   {
      get { return current; }
      set {
         TemperatureInfo ti = new TemperatureInfo();
         ti.Temperature = value;
         ti.Recorded = DateTimeOffset.UtcNow;
         previous = current;
         current = value;
         if (Math.Abs(current - previous) >= tolerance)
            raise_TemperatureChanged(new TemperatureChangedEventArgs(previous, current, ti.Recorded));
      }
   }

   public void raise_TemperatureChanged(TemperatureChangedEventArgs eventArgs)
   {
      if (TemperatureChanged == null)
         return;

      foreach (TemperatureChanged d in TemperatureChanged.GetInvocationList()) {
         if (d.Method.Name.Contains("Duplicate"))
            Console.WriteLine("Duplicate event handler; event handler not executed.");
         else
            d.Invoke(this, eventArgs);
      }
   }
}

public class Example
{
   public Temperature temp;

   public static void Main()
   {
      Example ex = new Example();
   }

   public Example()
   {
      temp = new Temperature(65, 3);
      temp.TemperatureChanged += this.TemperatureNotification;
      RecordTemperatures();
      Example ex = new Example(temp);
      ex.RecordTemperatures();
   }

   public Example(Temperature t)
   {
      temp = t;
      RecordTemperatures();
   }

   public void RecordTemperatures()
   {
      temp.TemperatureChanged += this.DuplicateTemperatureNotification;
      temp.CurrentTemperature = 66;
      temp.CurrentTemperature = 63;
   }

   internal void TemperatureNotification(Object sender, TemperatureChangedEventArgs e)
   {
      Console.WriteLine($"Notification 1: The temperature changed from {e.OldTemperature} to {e.CurrentTemperature}");
   }

   public void DuplicateTemperatureNotification(Object sender, TemperatureChangedEventArgs e)
   {
      Console.WriteLine($"Notification 2: The temperature changed from {e.OldTemperature} to {e.CurrentTemperature}");
   }
}
Imports System.Collections
Imports System.Collections.Generic

<Assembly: CLSCompliant(True)>

Public Class TemperatureChangedEventArgs : Inherits EventArgs
    Private originalTemp As Decimal
    Private newTemp As Decimal
    Private [when] As DateTimeOffset

    Public Sub New(original As Decimal, [new] As Decimal, [time] As DateTimeOffset)
        originalTemp = original
        newTemp = [new]
        [when] = [time]
    End Sub

    Public ReadOnly Property OldTemperature As Decimal
        Get
            Return originalTemp
        End Get
    End Property

    Public ReadOnly Property CurrentTemperature As Decimal
        Get
            Return newTemp
        End Get
    End Property

    Public ReadOnly Property [Time] As DateTimeOffset
        Get
            Return [when]
        End Get
    End Property
End Class

Public Delegate Sub TemperatureChanged(sender As Object, e As TemperatureChangedEventArgs)

Public Class Temperature
    Private Structure TemperatureInfo
        Dim Temperature As Decimal
        Dim Recorded As DateTimeOffset
    End Structure

    Public Event TemperatureChanged As TemperatureChanged

    Private previous As Decimal
    Private current As Decimal
    Private tolerance As Decimal
    Private tis As New List(Of TemperatureInfo)

    Public Sub New(temperature As Decimal, tolerance As Decimal)
        current = temperature
        Dim ti As New TemperatureInfo()
        ti.Temperature = temperature
        ti.Recorded = DateTimeOffset.UtcNow
        tis.Add(ti)
        Me.tolerance = tolerance
    End Sub

    Public Property CurrentTemperature As Decimal
        Get
            Return current
        End Get
        Set
            Dim ti As New TemperatureInfo
            ti.Temperature = value
            ti.Recorded = DateTimeOffset.UtcNow
            previous = current
            current = value
            If Math.Abs(current - previous) >= tolerance Then
                raise_TemperatureChanged(New TemperatureChangedEventArgs(previous, current, ti.Recorded))
            End If
        End Set
    End Property

    Public Sub raise_TemperatureChanged(eventArgs As TemperatureChangedEventArgs)
        If TemperatureChangedEvent Is Nothing Then Exit Sub

        Dim ListenerList() As System.Delegate = TemperatureChangedEvent.GetInvocationList()
        For Each d As TemperatureChanged In TemperatureChangedEvent.GetInvocationList()
            If d.Method.Name.Contains("Duplicate") Then
                Console.WriteLine("Duplicate event handler; event handler not executed.")
            Else
                d.Invoke(Me, eventArgs)
            End If
        Next
    End Sub
End Class

Public Class Example
    Public WithEvents temp As Temperature

    Public Shared Sub Main()
        Dim ex As New Example()
    End Sub

    Public Sub New()
        temp = New Temperature(65, 3)
        RecordTemperatures()
        Dim ex As New Example(temp)
        ex.RecordTemperatures()
    End Sub

    Public Sub New(t As Temperature)
        temp = t
        RecordTemperatures()
    End Sub

    Public Sub RecordTemperatures()
        temp.CurrentTemperature = 66
        temp.CurrentTemperature = 63

    End Sub

    Friend Shared Sub TemperatureNotification(sender As Object, e As TemperatureChangedEventArgs) _
           Handles temp.TemperatureChanged
        Console.WriteLine("Notification 1: The temperature changed from {0} to {1}", e.OldTemperature, e.CurrentTemperature)
    End Sub

    Friend Shared Sub DuplicateTemperatureNotification(sender As Object, e As TemperatureChangedEventArgs) _
           Handles temp.TemperatureChanged
        Console.WriteLine("Notification 2: The temperature changed from {0} to {1}", e.OldTemperature, e.CurrentTemperature)
    End Sub
End Class

Aşırı Yüklemeler

Ortak Dil Belirtimi, aşırı yüklenmiş üyelere aşağıdaki gereksinimleri uygular:

  • Üyeler, parametre sayısına ve herhangi bir parametrenin türüne göre aşırı yüklenebilir. Çağırma kuralı, dönüş türü, yönteme veya parametresine uygulanan özel değiştiriciler ve aşırı yüklemeler arasında ayrım yaparken parametrelerin değerle mi yoksa başvuruyla mı geçirildiği dikkate alınmaz. Örneğin, Adlandırma kuralları bölümünde adların bir kapsam içinde benzersiz olması gerektiği gereksiniminin koduna bakın.

  • Yalnızca özellikler ve yöntemler aşırı yüklenebilir. Alanlar ve olaylara çoklu görev verilemez.

  • Genel yöntemler, genel parametrelerinin sayısına göre aşırı yüklenebilir.

Uyarı

op_Explicit ve op_Implicit işleçleri, dönüş değerinin aşırı yükleme çözümlemesi için yöntem imzasının parçası olarak değerlendirilmediği kuralın istisnalarıdır. Bu iki işleç hem parametrelerine hem de dönüş değerlerine göre aşırı yüklenebilir.

Özel durumlar

Özel durum nesnelerinin System.Exception'dan veya System.Exception'den türetilmiş başka bir türden olması gerekir. Aşağıdaki örnekte, özel durum işleme için ErrorClass adlı bir özel sınıf kullanıldığında oluşan derleyici hatası gösterilmektedir.

using System;

[assembly: CLSCompliant(true)]

public class ErrorClass
{
   string msg;

   public ErrorClass(string errorMessage)
   {
      msg = errorMessage;
   }

   public string Message
   {
      get { return msg; }
   }
}

public static class StringUtilities
{
   public static string[] SplitString(this string value, int index)
   {
      if (index < 0 | index > value.Length) {
         ErrorClass badIndex = new ErrorClass("The index is not within the string.");
         throw badIndex;
      }
      string[] retVal = { value.Substring(0, index - 1),
                          value.Substring(index) };
      return retVal;
   }
}
// Compilation produces a compiler error like the following:
//    Exceptions1.cs(26,16): error CS0155: The type caught or thrown must be derived from
//            System.Exception
Imports System.Runtime.CompilerServices

<Assembly: CLSCompliant(True)>

Public Class ErrorClass
    Dim msg As String

    Public Sub New(errorMessage As String)
        msg = errorMessage
    End Sub

    Public ReadOnly Property Message As String
        Get
            Return msg
        End Get
    End Property
End Class

Public Module StringUtilities
    <Extension()> Public Function SplitString(value As String, index As Integer) As String()
        If index < 0 Or index > value.Length Then
            Dim BadIndex As New ErrorClass("The index is not within the string.")
            Throw BadIndex
        End If
        Dim retVal() As String = {value.Substring(0, index - 1),
                                   value.Substring(index)}
        Return retVal
    End Function
End Module
' Compilation produces a compiler error like the following:
'    Exceptions1.vb(27) : error BC30665: 'Throw' operand must derive from 'System.Exception'.
'    
'             Throw BadIndex
'             ~~~~~~~~~~~~~~

Bu hatayı düzeltmek için ErrorClass sınıfının System.Exception'den devralması gerekir. Ayrıca, Message özelliği geçersiz kılınmalıdır. Aşağıdaki örnek, CLS uyumlu bir ErrorClass sınıfı tanımlamak için bu hataları düzeltmektedir.

using System;

[assembly: CLSCompliant(true)]

public class ErrorClass : Exception
{
   string msg;

   public ErrorClass(string errorMessage)
   {
      msg = errorMessage;
   }

   public override string Message
   {
      get { return msg; }
   }
}

public static class StringUtilities
{
   public static string[] SplitString(this string value, int index)
   {
      if (index < 0 | index > value.Length) {
         ErrorClass badIndex = new ErrorClass("The index is not within the string.");
         throw badIndex;
      }
      string[] retVal = { value.Substring(0, index - 1),
                          value.Substring(index) };
      return retVal;
   }
}
Imports System.Runtime.CompilerServices

<Assembly: CLSCompliant(True)>

Public Class ErrorClass : Inherits Exception
    Dim msg As String

    Public Sub New(errorMessage As String)
        msg = errorMessage
    End Sub

    Public Overrides ReadOnly Property Message As String
        Get
            Return msg
        End Get
    End Property
End Class

Public Module StringUtilities
    <Extension()> Public Function SplitString(value As String, index As Integer) As String()
        If index < 0 Or index > value.Length Then
            Dim BadIndex As New ErrorClass("The index is not within the string.")
            Throw BadIndex
        End If
        Dim retVal() As String = {value.Substring(0, index - 1),
                                   value.Substring(index)}
        Return retVal
    End Function
End Module

Özellikler

.NET derlemelerinde, özel öznitelikler özel öznitelikleri depolamak ve derlemeler, türler, üyeler ve yöntem parametreleri gibi programlama nesneleri hakkında meta verileri almak için genişletilebilir bir mekanizma sağlar. Özel öznitelikler System.Attribute veya System.Attribute bir türevden türetilmelidir.

Aşağıdaki örnek bu kuralı ihlal eder. NumericAttribute, System.Attribute'den türetilmeyen bir sınıfı tanımlar. Derleyici hatası yalnızca CLS uyumlu olmayan öznitelik uygulandığında sonuçlanır, sınıf tanımlandığında olmaz.

using System;

[assembly: CLSCompliant(true)]

[AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Struct)]
public class NumericAttribute
{
   private bool _isNumeric;

   public NumericAttribute(bool isNumeric)
   {
      _isNumeric = isNumeric;
   }

   public bool IsNumeric
   {
      get { return _isNumeric; }
   }
}

[Numeric(true)] public struct UDouble
{
   double Value;
}
// Compilation produces a compiler error like the following:
//    Attribute1.cs(22,2): error CS0616: 'NumericAttribute' is not an attribute class
//    Attribute1.cs(7,14): (Location of symbol related to previous error)
<Assembly: CLSCompliant(True)>

<AttributeUsageAttribute(AttributeTargets.Class Or AttributeTargets.Struct)> _
Public Class NumericAttribute
    Private _isNumeric As Boolean

    Public Sub New(isNumeric As Boolean)
        _isNumeric = isNumeric
    End Sub

    Public ReadOnly Property IsNumeric As Boolean
        Get
            Return _isNumeric
        End Get
    End Property
End Class

<Numeric(True)> Public Structure UDouble
    Dim Value As Double
End Structure
' Compilation produces a compiler error like the following:
'    error BC31504: 'NumericAttribute' cannot be used as an attribute because it 
'    does not inherit from 'System.Attribute'.
'    
'    <Numeric(True)> Public Structure UDouble
'     ~~~~~~~~~~~~~

CLS uyumlu özniteliğin oluşturucu veya özellikleri yalnızca aşağıdaki türleri kullanıma açabilir:

Aşağıdaki örnek, DescriptionAttributeÖzniteliğinden türetilen bir sınıfını tanımlar. Sınıf oluşturucu Descriptortüründe bir parametreye sahiptir, bu nedenle sınıf CLS uyumlu değildir. C# derleyicisi bir uyarı yayar ancak başarıyla derlenirken Visual Basic derleyicisi bir uyarı veya hata yaymaz.

using System;

[assembly:CLSCompliantAttribute(true)]

public enum DescriptorType { type, member };

public class Descriptor
{
   public DescriptorType Type;
   public String Description;
}

[AttributeUsage(AttributeTargets.All)]
public class DescriptionAttribute : Attribute
{
   private Descriptor desc;

   public DescriptionAttribute(Descriptor d)
   {
      desc = d;
   }

   public Descriptor Descriptor
   { get { return desc; } }
}
// Attempting to compile the example displays output like the following:
//       warning CS3015: 'DescriptionAttribute' has no accessible
//               constructors which use only CLS-compliant types
<Assembly: CLSCompliantAttribute(True)>

Public Enum DescriptorType As Integer
    Type = 0
    Member = 1
End Enum

Public Class Descriptor
    Public Type As DescriptorType
    Public Description As String
End Class

<AttributeUsage(AttributeTargets.All)> _
Public Class DescriptionAttribute : Inherits Attribute
    Private desc As Descriptor

    Public Sub New(d As Descriptor)
        desc = d
    End Sub

    Public ReadOnly Property Descriptor As Descriptor
        Get
            Return desc
        End Get
    End Property
End Class

CLSCompliantAttribute özniteliği

CLSCompliantAttribute özniteliği, program öğesinin Ortak Dil Belirtimine uygun olup olmadığını belirtmek için kullanılır. CLSCompliantAttribute(Boolean) oluşturucu, program öğesinin CLS uyumlu olup olmadığını gösteren isComplianttek bir gerekli parametre içerir.

Derleme zamanında, derleyici CLS uyumlu olduğu varsayılan uyumlu olmayan öğeleri algılar ve bir uyarı yayar. Derleyici, açıkça uyumsuz olarak bildirilen türler veya üyeler için uyarı yaymaz.

Bileşen geliştiricileri CLSCompliantAttribute özniteliğini iki şekilde kullanabilir:

  • ClS uyumlu bir bileşen tarafından kullanıma sunulan ortak arabirimin bölümlerini ve CLS uyumlu olmayan bölümleri tanımlamak için. Özniteliği, belirli program öğelerini CLS uyumlu olarak işaretlemek için kullanıldığında, bu öğelerin .NET'i hedefleyen tüm dillerden ve araçlardan erişilebilir olmasını garanti eder.

  • Bileşen kitaplığının ortak arabiriminin yalnızca CLS uyumlu program öğelerini kullanıma sunmasını sağlamak için. Öğeler CLS uyumlu değilse, derleyiciler genellikle bir uyarı yayınlar.

Uyarı

Bazı durumlarda dil derleyicileri, CLSCompliantAttribute özniteliğinin kullanılıp kullanılmadığına bakılmaksızın CLS uyumlu kuralları zorunlu kılar. Örneğin, bir arabirimde statik üye tanımlamak CLS kuralını ihlal eder. Bu bağlamda, arabirimde bir static (C#'ta) veya Shared (Visual Basic'te) üyesi tanımlarsanız, hem C# hem de Visual Basic derleyicileri bir hata iletisi görüntüler ve uygulamayı derleyemezseniz.

CLSCompliantAttribute özniteliği, AttributeUsageAttributedeğerine sahip bir AttributeTargets.All özniteliğiyle işaretlenir. Bu değer, derlemeler, modüller, türler (sınıflar, yapılar, numaralandırmalar, arabirimler ve temsilciler), tür üyeleri (oluşturucular, yöntemler, özellikler, alanlar ve olaylar), parametreler, genel parametreler ve dönüş değerleri dahil olmak üzere herhangi bir program öğesine CLSCompliantAttribute özniteliğini uygulamanızı sağlar. Ancak uygulamada özniteliğini yalnızca derlemelere, türlere ve tür üyelerine uygulamanız gerekir. Aksi takdirde, derleyiciler özniteliği yoksayar ve kitaplığınızdaki genel arabirimde uyumsuz bir parametre, genel parametre veya dönüş değeriyle karşılaştıklarında derleyici uyarıları üretmeye devam eder.

CLSCompliantAttribute özniteliğinin değeri, kapsanan program öğeleri tarafından devralınır. Örneğin, bir derleme CLS uyumlu olarak işaretlenirse türleri de CLS uyumlu olur. Bir tür CLS uyumlu olarak işaretlenirse, iç içe türleri ve üyeleri de CLS uyumlu olur.

CLSCompliantAttribute özniteliğini kapsanan bir program öğesine uygulayarak devralınan uyumluluğu açıkça geçersiz kılabilirsiniz. Örneğin, uyumlu bir derlemede uyumlu olmayan bir tür tanımlamak için CLSCompliantAttribute özniteliğini isCompliantfalse değeriyle kullanabilir ve uyumlu olmayan bir derlemede uyumlu bir tür tanımlamak için isComplianttrue değeriyle özniteliğini kullanabilirsiniz. Uyumlu olmayan üyeleri uyumlu bir türde de tanımlayabilirsiniz. Ancak uyumlu olmayan bir türün uyumlu üyeleri olamaz, bu yüzden uyumlu olmayan bir türden devralmayı "geçersiz kılmak" için isCompliant değerine true olan özniteliği kullanamazsınız.

Bileşenleri geliştirirken derlemenizin, türlerinin ve üyelerinin CLS uyumlu olup olmadığını belirtmek için her zaman CLSCompliantAttribute özniteliğini kullanmanız gerekir.

CLS uyumlu bileşenler oluşturmak için:

  1. Derlemenizi CLS uyumlu olarak işaretlemek için CLSCompliantAttribute kullanın.

  2. Derlemede CLS uyumlu olmayan açığa çıkarılan türleri uyumsuz olarak işaretleyin.

  3. CLS uyumlu türlerde halka açık üyeleri uyumsuz olarak işaretleyin.

  4. CLS uyumlu olmayan üyeler için CLS uyumlu bir alternatif sağlayın.

Uyumlu olmayan tüm türlerinizi ve üyelerinizi başarıyla işaretlediyseniz, derleyiciniz herhangi bir uyumsuzluk uyarısı yaymamalıdır. Ancak, hangi üyelerin CLS uyumlu olmadığını belirtmeli ve cls uyumlu alternatiflerini ürün belgelerinizde listelemelisiniz.

Aşağıdaki örnek, CLS uyumlu bir derlemeyi ve iki CLS uyumlu olmayan üyesi olan CLSCompliantAttributetürünü tanımlamak için CharacterUtilities özniteliğini kullanır. Her iki üye de CLSCompliant(false) özniteliğiyle etiketlenmiş olduğundan, derleyici hiçbir uyarı üretmez. sınıfı, her iki yöntem için de CLS uyumlu bir alternatif sağlar. Normalde, CLS uyumlu alternatifler sağlamak için ToUTF16 yöntemine yalnızca iki aşırı yükleme eklerdik. Ancak, yöntemler dönüş değerine göre aşırı yüklenemediğinden, CLS uyumlu yöntemlerin adları uyumlu olmayan yöntemlerin adlarından farklıdır.

using System;
using System.Text;

[assembly:CLSCompliant(true)]

public class CharacterUtilities
{
   [CLSCompliant(false)] public static ushort ToUTF16(String s)
   {
      s = s.Normalize(NormalizationForm.FormC);
      return Convert.ToUInt16(s[0]);
   }

   [CLSCompliant(false)] public static ushort ToUTF16(Char ch)
   {
      return Convert.ToUInt16(ch);
   }

   // CLS-compliant alternative for ToUTF16(String).
   public static int ToUTF16CodeUnit(String s)
   {
      s = s.Normalize(NormalizationForm.FormC);
      return (int) Convert.ToUInt16(s[0]);
   }

   // CLS-compliant alternative for ToUTF16(Char).
   public static int ToUTF16CodeUnit(Char ch)
   {
      return Convert.ToInt32(ch);
   }

   public bool HasMultipleRepresentations(String s)
   {
      String s1 = s.Normalize(NormalizationForm.FormC);
      return s.Equals(s1);
   }

   public int GetUnicodeCodePoint(Char ch)
   {
      if (Char.IsSurrogate(ch))
         throw new ArgumentException("ch cannot be a high or low surrogate.");

      return Char.ConvertToUtf32(ch.ToString(), 0);
   }

   public int GetUnicodeCodePoint(Char[] chars)
   {
      if (chars.Length > 2)
         throw new ArgumentException("The array has too many characters.");

      if (chars.Length == 2) {
         if (! Char.IsSurrogatePair(chars[0], chars[1]))
            throw new ArgumentException("The array must contain a low and a high surrogate.");
         else
            return Char.ConvertToUtf32(chars[0], chars[1]);
      }
      else {
         return Char.ConvertToUtf32(chars.ToString(), 0);
      }
   }
}
Imports System.Text

<Assembly: CLSCompliant(True)>

Public Class CharacterUtilities
    <CLSCompliant(False)> Public Shared Function ToUTF16(s As String) As UShort
        s = s.Normalize(NormalizationForm.FormC)
        Return Convert.ToUInt16(s(0))
    End Function

    <CLSCompliant(False)> Public Shared Function ToUTF16(ch As Char) As UShort
        Return Convert.ToUInt16(ch)
    End Function

    ' CLS-compliant alternative for ToUTF16(String).
    Public Shared Function ToUTF16CodeUnit(s As String) As Integer
        s = s.Normalize(NormalizationForm.FormC)
        Return CInt(Convert.ToInt16(s(0)))
    End Function

    ' CLS-compliant alternative for ToUTF16(Char).
    Public Shared Function ToUTF16CodeUnit(ch As Char) As Integer
        Return Convert.ToInt32(ch)
    End Function

    Public Function HasMultipleRepresentations(s As String) As Boolean
        Dim s1 As String = s.Normalize(NormalizationForm.FormC)
        Return s.Equals(s1)
    End Function

    Public Function GetUnicodeCodePoint(ch As Char) As Integer
        If Char.IsSurrogate(ch) Then
            Throw New ArgumentException("ch cannot be a high or low surrogate.")
        End If
        Return Char.ConvertToUtf32(ch.ToString(), 0)
    End Function

    Public Function GetUnicodeCodePoint(chars() As Char) As Integer
        If chars.Length > 2 Then
            Throw New ArgumentException("The array has too many characters.")
        End If
        If chars.Length = 2 Then
            If Not Char.IsSurrogatePair(chars(0), chars(1)) Then
                Throw New ArgumentException("The array must contain a low and a high surrogate.")
            Else
                Return Char.ConvertToUtf32(chars(0), chars(1))
            End If
        Else
            Return Char.ConvertToUtf32(chars.ToString(), 0)
        End If
    End Function
End Class

Kitaplık yerine uygulama geliştiriyorsanız (başka bir deyişle, diğer uygulama geliştiricileri tarafından kullanılabilecek türleri veya üyeleri göstermiyorsanız), uygulamanızın kullandığı program öğelerinin CLS uyumluluğu yalnızca diliniz bunları desteklemiyorsa ilgi çekicidir. Bu durumda, CLS uyumlu olmayan bir öğeyi kullanmaya çalıştığınızda dil derleyiciniz bir hata oluşturur.

Diller arası birlikte çalışabilirlik

Dil bağımsızlığının birkaç olası anlamı vardır. Bir anlamı, başka bir dilde yazılmış bir uygulamadan bir dilde yazılmış türleri sorunsuz bir şekilde tüketmeyi içerir. Bu makalenin odak noktası olan ikinci bir anlam, birden çok dilde yazılmış kodu tek bir .NET derlemesinde birleştirmeyi içerir.

Aşağıdaki örnek, NumericLib ve StringLibolmak üzere iki sınıf içeren Utilities.dll adlı bir sınıf kitaplığı oluşturarak diller arası birlikte çalışabilirliği gösterir. NumericLib sınıfı C# dilinde, StringLib sınıfı ise Visual Basic'te yazılır. StringUtil.vb sınıfında tek bir üye ToTitleCaseiçeren StringLibkaynak kodu aşağıdadır.

Imports System.Collections.Generic
Imports System.Runtime.CompilerServices

Public Module StringLib
    Private exclusions As List(Of String)

    Sub New()
        Dim words() As String = {"a", "an", "and", "of", "the"}
        exclusions = New List(Of String)
        exclusions.AddRange(words)
    End Sub

    <Extension()> _
    Public Function ToTitleCase(title As String) As String
        Dim words() As String = title.Split()
        Dim result As String = String.Empty

        For ctr As Integer = 0 To words.Length - 1
            Dim word As String = words(ctr)
            If ctr = 0 OrElse Not exclusions.Contains(word.ToLower()) Then
                result += word.Substring(0, 1).ToUpper() + _
                          word.Substring(1).ToLower()
            Else
                result += word.ToLower()
            End If
            If ctr <= words.Length - 1 Then
                result += " "
            End If
        Next
        Return result
    End Function
End Module

NumberUtil.cs'nin kaynak kodu, iki üyesi NumericLib ve IsEvenolan bir NearZero sınıfını tanımlar.

using System;

public static class NumericLib
{
   public static bool IsEven(this IConvertible number)
   {
      if (number is Byte ||
          number is SByte ||
          number is Int16 ||
          number is UInt16 ||
          number is Int32 ||
          number is UInt32 ||
          number is Int64)
         return Convert.ToInt64(number) % 2 == 0;
      else if (number is UInt64)
         return ((ulong) number) % 2 == 0;
      else
         throw new NotSupportedException("IsEven called for a non-integer value.");
   }

   public static bool NearZero(double number)
   {
      return Math.Abs(number) < .00001;
   }
}

İki sınıfı tek bir derlemede paketlemek için bunları modüller halinde derlemeniz gerekir. Visual Basic kaynak kodu dosyasını bir modülde derlemek için şu komutu kullanın:

vbc /t:module StringUtil.vb

Visual Basic derleyicisinin komut satırı söz dizimi hakkında daha fazla bilgi için bkz. Komut Satırı'ndan Derleme.

C# kaynak kodu dosyasını bir modülde derlemek için şu komutu kullanın:

csc /t:module NumberUtil.cs

Ardından, iki modülü bir derlemede derlemek için Bağlayıcı seçeneklerini kullanırsınız:

link numberutil.netmodule stringutil.netmodule /out:UtilityLib.dll /dll

Aşağıdaki örnek daha sonra NumericLib.NearZero ve StringLib.ToTitleCase yöntemlerini çağırır. Hem Visual Basic kodu hem de C# kodu her iki sınıftaki yöntemlere erişebilir.

using System;

public class Example
{
   public static void Main()
   {
      Double dbl = 0.0 - Double.Epsilon;
      Console.WriteLine(NumericLib.NearZero(dbl));

      string s = "war and peace";
      Console.WriteLine(s.ToTitleCase());
   }
}
// The example displays the following output:
//       True
//       War and Peace
Module Example
    Public Sub Main()
        Dim dbl As Double = 0.0 - Double.Epsilon
        Console.WriteLine(NumericLib.NearZero(dbl))

        Dim s As String = "war and peace"
        Console.WriteLine(s.ToTitleCase())
    End Sub
End Module
' The example displays the following output:
'       True
'       War and Peace

Visual Basic kodunu derlemek için şu komutu kullanın:

vbc example.vb /r:UtilityLib.dll

C# ile derlemek için, derleyicinin adını vbc yerine cscolarak değiştirin ve dosya uzantısını .vb olarak .csolarak değiştirin:

csc example.cs /r:UtilityLib.dll