'Kullanma' yönergeleri ad alanının içinde mi yoksa dışında mı olmalı?


2060

StyleCop bazı C # kodu üzerinde çalışıyorum ve usingyönergelerimi ad alanı içinde olması gerektiğini bildiriyor .

usingYönergeleri ad alanının dışına koymak yerine teknik bir neden var mı ?


4
Bazen, kullanıcıları nereye koyduğunuzda fark yaratır: stackoverflow.com/questions/292535/linq-to-sql-designer-bug
gius

82
Sadece referans olarak, dosya başına birden fazla sınıf sorununun ötesinde sonuçlar vardır, bu nedenle bu soruya yeniyseniz lütfen okumaya devam edin.
Charlie

3
@ user-12506 - bu, bazı düzeylerde kod tutarlılığının gerekli olduğu orta ila büyük geliştirme ekibinde çok iyi sonuç vermez. Daha önce de belirtildiği gibi, farklı düzenleri anlamadıysanız, beklediğiniz gibi çalışmayan uç durumlar bulabilirsiniz.
benPearce

34
Terminoloji: Bunlar olmayan using ifadeleri ; onlar using direktiflerdir . usingÖte yandan, bir ifade, bir yöntem gövdesi vb. İçindeki diğer deyimlerle birlikte ortaya çıkan bir dil yapısıdır. Örnek olarak, using (var e = s.GetEnumerator()) { /* ... */ }gevşek bir şekilde aynı olan bir deyimdir var e = s.GetEnumerator(); try { /* ... */ } finally { if (e != null) { e.Dispose(); } }.
Jeppe Stig Nielsen

1
Bu zaten herkes tarafından belirtilmeyen ise, aslında, Microsoft da koyarak önerir usingiçindeki ifadeleri namespacekendi içinde, bildirimleri iç kodlama ışık tutmaktadır
user1451111

Yanıtlar:


2132

Aslında ikisi arasında (ince) bir fark vardır. File1.cs içinde aşağıdaki kodu olduğunu düşünün:

// File1.cs
using System;
namespace Outer.Inner
{
    class Foo
    {
        static void Bar()
        {
            double d = Math.PI;
        }
    }
}

Şimdi birisinin projeye şöyle görünen başka bir dosya (Dosya2.cs) eklediğini düşünün:

// File2.cs
namespace Outer
{
    class Math
    {
    }
}

Derleyici , ad alanının dışındaki yönergelere Outerbakmadan önce arama yapar using, Outer.Mathbunun yerine bulur System.Math. Ne yazık ki (ya da neyse ki?), Üyesi Outer.Mathyok PI, bu yüzden Dosya1 artık bozuk.

Bu using, ad alanı beyanınızın içine aşağıdaki gibi koyarsanız değişir :

// File1b.cs
namespace Outer.Inner
{
    using System;
    class Foo
    {
        static void Bar()
        {
            double d = Math.PI;
        }
    }
}

Derleyici arama Systemyapmadan önce arar Outer, bulur System.Mathve her şey yolunda.

Bazıları bunun Mathkullanıcı tanımlı bir sınıf için kötü bir isim olabileceğini savunur , çünkü zaten bir tane vardır System; nokta burada orada sadece budur olduğunu fark ve bu senin kod yaşatılabilirlik etkiler.

Ayrıca Foo, ad alanında Outerdeğil, ne olduğunu not etmek de ilginçtir Outer.Inner. Bu durumda, Outer.MathDosya2'yi eklemek nereye usinggiderse gitsin Dosya1'i keser . Bu, derleyicinin herhangi bir usingyönergeye bakmadan önce en içteki ad alanında arama yaptığı anlamına gelir .


28
Bu, ifadeleri yerel olarak Mark'ın birden çok ad-alan-içinde-dosya argümanından kullanmak için çok daha iyi bir nedendir. Özellikle derleme kutusunu işaretleyin ve ad çakışması hakkında şikayette bulunun (bu kural için StyleCop belgelerine bakın (örneğin Jared tarafından yayınlanmıştır)).
David Schmitt

148
Kabul edilen cevap iyidir, ancak bana göre kullanma maddelerini ad alanının dışına koymak iyi bir neden gibi görünüyor . Outer.Inner ad alanındaysanız, System.Math yerine Outer.Inner öğesinden Math sınıfını kullanmasını beklerim.
Frank Wallis

7
Ben de buna katılıyorum. Kabul edilen cevap, farkı teknik olarak tanımlaması bakımından doğrudur. Ancak, bir veya diğer sınıfın açık bir ek bilgiye ihtiyacı olacaktır. Ben çok ratehr "Math" kendi yerel sınıfa çözmek olurdu ve "System.Math" dış sınıf bakın - Outer.Math önce "Math" olarak kullanılıyor olsa bile. Evet, önceden var olan birçok referansı düzeltmek daha fazla iştir, ancak bu aynı zamanda Outer.Math'in farklı bir adı olması gereken bir ipucu da olabilir!
mbmcavoy

13
Harika bir yanıt, ama bana öyle geliyor ki, sadece yerel olarak ifadeleri kullanarak çerçeve dışı koymak ve ifadeleri kullanarak çerçeveyi küresel tutmak istiyorum. Tercihimi neden tamamen değiştirmem gerektiğine dair daha fazla kimse var mı? Ayrıca bu nereden geldi, VS2008'deki şablonlar ad alanının dışında kullanılmaya başlandı?
Timin

31
Bence bu, kullanım yerinizi değiştirmek yerine kötü bir adlandırma kuralı. Çözümünüzde Math adında bir sınıf olmamalıdır
jDeveloper

454

Bu konu zaten bazı harika cevaplara sahip, ancak bu ek cevapla biraz daha ayrıntı getirebileceğimi hissediyorum.

İlk olarak, noktalarla birlikte bir ad alanı bildirimi unutmayın:

namespace MyCorp.TheProduct.SomeModule.Utilities
{
    ...
}

tamamen şuna eşittir:

namespace MyCorp
{
    namespace TheProduct
    {
        namespace SomeModule
        {
            namespace Utilities
            {
                ...
            }
        }
    }
}

İsterseniz using, tüm bu seviyelere direktifler koyabilirsiniz . (Tabii ki, usingsadece bir yerde olmak istiyoruz , ancak dile göre yasal olacaktır.)

: Hangi tip ima çözülmesi için kural, gevşek böyle ifade edilebilir hiçbir şey bu kadar bir sonraki kapsama bir düzey dışarı çıkmak ve orada arama orada bulunan ve eğer Birincisi, maç için iç-en "kapsam" arama , bir eşleşme bulunana kadar. Bir düzeyde birden fazla eşleşme bulunursa, türlerden biri geçerli derlemeden geliyorsa, bunu seçin ve derleyici uyarısı verin. Aksi takdirde vazgeçiniz (derleme zamanı hatası).

Şimdi, bunun iki büyük sözleşmeyle somut bir örnekte ne anlama geldiğini açıklayalım.

(1) dışında kullanımları ile:

using System;
using System.Collections.Generic;
using System.Linq;
//using MyCorp.TheProduct;  <-- uncommenting this would change nothing
using MyCorp.TheProduct.OtherModule;
using MyCorp.TheProduct.OtherModule.Integration;
using ThirdParty;

namespace MyCorp.TheProduct.SomeModule.Utilities
{
    class C
    {
        Ambiguous a;
    }
}

Yukarıdaki durumda, ne tür Ambiguousolduğunu bulmak için arama şu sırayla yapılır:

  1. İçerideki Cyuvalanmış türler (miras alınan yuvalanmış türler dahil)
  2. Geçerli ad alanındaki türler MyCorp.TheProduct.SomeModule.Utilities
  3. Ad alanındaki türler MyCorp.TheProduct.SomeModule
  4. Türleri MyCorp.TheProduct
  5. Türleri MyCorp
  6. Boş ad alanındaki türler (genel ad alanı)
  7. Türleri içinde System, System.Collections.Generic, System.Linq, MyCorp.TheProduct.OtherModule, MyCorp.TheProduct.OtherModule.Integration, veThirdParty

Diğer sözleşme:

(2) İçindeki kullanımlarla:

namespace MyCorp.TheProduct.SomeModule.Utilities
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using MyCorp.TheProduct;                           // MyCorp can be left out; this using is NOT redundant
    using MyCorp.TheProduct.OtherModule;               // MyCorp.TheProduct can be left out
    using MyCorp.TheProduct.OtherModule.Integration;   // MyCorp.TheProduct can be left out
    using ThirdParty;

    class C
    {
        Ambiguous a;
    }
}

Şimdi, türü arayın Ambiguousşu sırayla gider:

  1. İçerideki Cyuvalanmış türler (miras alınan yuvalanmış türler dahil)
  2. Geçerli ad alanındaki türler MyCorp.TheProduct.SomeModule.Utilities
  3. Türleri içinde System, System.Collections.Generic, System.Linq, MyCorp.TheProduct, MyCorp.TheProduct.OtherModule, MyCorp.TheProduct.OtherModule.Integration, veThirdParty
  4. Ad alanındaki türler MyCorp.TheProduct.SomeModule
  5. Türleri MyCorp
  6. Boş ad alanındaki türler (genel ad alanı)

(Bunun MyCorp.TheProduct"3" ün bir parçası olduğunu ve bu nedenle "4." ile "5." arasında gerekli olmadığını unutmayın.)

son sözler

Kullanıcıları ad alanı bildiriminin içine veya dışına koyarsanız da, daha sonra birisinin daha yüksek önceliğe sahip ad alanlarından birine aynı ada sahip yeni bir tür ekleme olasılığı vardır.

Ayrıca, iç içe geçmiş bir ad alanı bir türle aynı ada sahipse, sorunlara neden olabilir.

Arama hiyerarşisi değiştiğinden ve başka bir tür bulunduğundan, kullanımları bir konumdan diğerine taşımak her zaman tehlikelidir. Bu nedenle, bir kongre seçin ve ona sadık kalın, böylece asla kullanıcıları hareket ettirmek zorunda kalmazsınız.

Visual Studio'nun şablonları, varsayılan olarak, kullanımları ad alanının dışına koyar (örneğin , VS'nin yeni bir dosyada yeni bir sınıf oluşturmasını sağlarsanız).

Usings sahip biri (küçük) avantajı dışında daha sonra örneğin bir küresel bir özellik için kullandığınız direktifleri kullanabilmesidir [assembly: ComVisible(false)]yerine [assembly: System.Runtime.InteropServices.ComVisible(false)].


46
Bu en iyi açıklamadır, çünkü 'using' ifadelerinin konumunun geliştiriciden kasıtlı bir karar olduğu gerçeğini vurgular. Hiçbir durumda, birisi 'kullanım' ifadelerinin yerini anlamlarını anlamadan dikkatsizce değiştirmemelidir. Bu nedenle StyleCop kuralı sadece aptal.
ZunTzu

194

Ad alanlarının içine yerleştirmek, bildirimleri dosya için o ad alanı için yerel hale getirir (dosyada birden fazla ad alanınız olması durumunda), ancak dosya başına yalnızca bir ad alanınız varsa, dışarı çıkıp çıkmadıkları veya ad alanının içinde.

using ThisNamespace.IsImported.InAllNamespaces.Here;

namespace Namespace1
{ 
   using ThisNamespace.IsImported.InNamespace1.AndNamespace2;

   namespace Namespace2
   { 
      using ThisNamespace.IsImported.InJustNamespace2;
   }       
}

namespace Namespace3
{ 
   using ThisNamespace.IsImported.InJustNamespace3;
}

ad alanları fiziksel (dosya) değil mantıksal bir ayrım sağlar.
Jowen

9
Fark olmadığı pek doğru değil; bloklar usingiçindeki yönergeler namespace, kapalı namespacebloğa dayalı göreli ad alanlarına atıfta bulunabilir .
VEYA Haritacı

70
Evet biliyorum. bu sorunun kabul edilen cevabında beş yıl önce belirledik.
Mark Cidade

59

Göre Hanselman - Yönergesi ve Montaj Yükleniyor ... kullanma ve diğer bu tür yazılar teknik bir fark yoktur.

Benim tercihim onları isim alanlarının dışına koymak.


3
@Chris M: uh ... cevaba gönderilen bağlantı , giriş ve çıkış için hiçbir fayda olmadığını gösterir , aslında postaladığınız bağlantıda yapılan iddiayı tahrif eden bir örnek gösterir ...
johnny

2
Evet tam olarak konu okumadım ama MVP'ler doğru olduğunu söylediğinde aldım. Bir adam onu ​​çürütür, açıklar ve kodunu daha aşağı gösterir ... "C # derleyicisinin oluşturduğu IL her iki durumda da aynıdır. Aslında C # derleyicisi, yönergeleri kullanarak her birine karşılık gelen hiçbir şey üretmez. C # ism ve .NET'in kendisi için bir anlamı yok. (İfadeleri kullanmak için doğru değil, ancak bunlar oldukça farklı bir şey.) " Groups.google.com/group/wpf-disciples/msg/781738deb0a15c46
Chris McKee

84
Lütfen bağlantının bir özetini ekleyin. Ne zaman bağlantısı kesik (çünkü olacaktır aniden 32 upvotes ile bir cevap sadece değer, gerçekleşmesi, yeterli zaman verilmiş) My style is to put them outside the namespaces.zar zor bir cevap hiç -.
ANeves

11
Buradaki iddia sadece yanlış ... teknik bir fark var ve kendi atıfınız böyle diyor ... aslında, hepsi bu. Lütfen bu yanlış yanıtı silin ... çok daha iyi ve doğru olanlar var.
Jim Balter

53

StyleCop Belgelerine Göre:

SA1200: UseDirectivesMustBePlacedWithinNamespace

Neden AC # yönergesini kullanarak bir ad alanı öğesinin dışına yerleştirilir.

Kural Açıklama Dosyada herhangi bir ad alanı öğesi bulunmadığı sürece, kullanım talimatı veya kullanım takma adı yönergesi bir ad alanı öğesinin dışına yerleştirildiğinde bu kuralın ihlali oluşur.

Örneğin, aşağıdaki kod bu kuralın iki ihlaline neden olur.

using System;
using Guid = System.Guid;

namespace Microsoft.Sample
{
    public class Program
    {
    }
}

Ancak aşağıdaki kod, bu kuralın herhangi bir ihlaline neden olmaz:

namespace Microsoft.Sample
{
    using System;
    using Guid = System.Guid;

    public class Program
    {
    }
}

Bu kod, derleyici hataları olmadan temiz bir şekilde derlenecektir. Ancak, Guid türünün hangi sürümünün tahsis edildiği belirsizdir. Using yönergesi, aşağıda gösterildiği gibi ad alanının içine taşınırsa, bir derleyici hatası oluşur:

namespace Microsoft.Sample
{
    using Guid = System.Guid;
    public class Guid
    {
        public Guid(string s)
        {
        }
    }

    public class Program
    {
        public static void Main(string[] args)
        {
            Guid g = new Guid("hello");
        }
    }
}

Kod, aşağıdaki satırda, derleme satırında bulunan başarısız Guid g = new Guid("hello");

CS0576: 'Microsoft.Sample' ad alanı, 'Guid' takma adıyla çakışan bir tanım içeriyor

Kod, Guid adlı System.Guid türüne bir diğer ad oluşturur ve aynı zamanda eşleşen bir yapıcı arabirimiyle Guid adlı kendi türünü oluşturur. Daha sonra kod, Guid türünün bir örneğini oluşturur. Bu örneği oluşturmak için, derleyicinin iki farklı Guid tanımı arasında seçim yapması gerekir. Using-alias yönergesi, ad alanı öğesinin dışına yerleştirildiğinde, derleyici, yerel ad alanında tanımlanan yerel Guid tanımını seçer ve ad alanının dışında tanımlanan use-alias yönergesini tamamen yoksayar. Ne yazık ki, bu kodu okurken belli değil.

Bununla birlikte, use-alias yönergesi ad alanı içinde konumlandırıldığında, derleyici aynı ad alanında tanımlanan iki farklı, çakışan Guid türü arasında seçim yapmak zorundadır. Bu türlerin her ikisi de eşleşen bir kurucu sağlar. Derleyici karar veremediğinden derleyici hatasını işaretler.

Using-alias yönergesini ad alanının dışına yerleştirmek kötü bir uygulamadır, çünkü bu tür durumlarda karışıklığa yol açabilir, burada türün hangi sürümünün gerçekten kullanıldığı açık değildir. Bu, teşhis edilmesi zor olabilecek bir hataya neden olabilir.

Use-alias yönergelerini ad alanı öğesi içine yerleştirmek hata kaynağı olarak bunu ortadan kaldırır.

  1. Birden Çok Ad Alanı

Birden çok ad alanı öğesini tek bir dosyaya yerleştirmek genellikle kötü bir fikirdir, ancak bu yapılırsa ve yapıldığında, tüm yönergelerin, genel olarak dosyanın üst kısmına değil, ad alanı öğelerinin her birine yerleştirilmesi iyi bir fikirdir. Bu, ad alanlarını sıkıca kaplayacak ve yukarıda açıklanan davranış türlerinden kaçınmaya yardımcı olacaktır.

Kod, ad alanının dışına yerleştirilmiş yönergeler kullanılarak yazıldığında, kodun anlambilimini değiştirmediğinden emin olmak için, bu yönergeleri ad alanı içinde taşırken dikkatli olunmalıdır. Yukarıda açıklandığı gibi, isim-alanı yönergelerinin ad-alanı elemanına yerleştirilmesi, derleyicinin, direktifler ad alanının dışına yerleştirildiğinde gerçekleşmeyecek şekilde çakışan türler arasında seçim yapmasına izin verir.

İhlallerin Düzeltilmesi Bu kuralın ihlalini gidermek için, ad alanı öğesindeki tüm yönergeleri ve takma ad kullanma yönergelerini taşıyın.


1
@Jared - cevabımda belirttiğim gibi, tercih ettiğim geçici çözüm / çözüm dosya başına sadece bir sınıfa sahip olmak. Bunun oldukça yaygın bir sözleşme olduğunu düşünüyorum.
benPearce

24
Gerçekten de bu bir StyleCop kuralı! SA1402: AC # belgesi, tüm sınıflar kısmi değilse ve aynı türde değilse, kök düzeyinde yalnızca tek bir sınıf içerebilir. Bir kuralı bir diğerini kırarak sergilemek sadece yanlış sosla damlar.
Görev

6
Aslında StyleCop perspektifinden kapsayan ilk cevap olduğu için seçildi. Şahsen usingisim alanının dışındaki görsel hissi seviyorum . İçim usingbana çok çirkin gözüküyor. :)
nawfal

2
Sonunda soruya iyi bir cevap. Ve benPearce'ın yorumu alakasız ... bunun dosyadaki sınıf sayısı ile ilgisi yok.
Jim Balter

35

Takma adlar kullanmak istediğinizde, ad alanının içine ifadeler kullanmakla ilgili bir sorun vardır. Takma ad, önceki usingifadelerden yararlanmaz ve tam olarak nitelenmesi gerekir.

Düşünmek:

namespace MyNamespace
{
    using System;
    using MyAlias = System.DateTime;

    class MyClass
    {
    }
}

karşı:

using System;

namespace MyNamespace
{
    using MyAlias = DateTime;

    class MyClass
    {
    }
}

Aşağıdaki gibi uzun soluklu bir takma adınız varsa bu özellikle telaffuz edilebilir (sorunu bu şekilde buldum):

using MyAlias = Tuple<Expression<Func<DateTime, object>>, Expression<Func<TimeSpan, object>>>;

İle usingad alanı içine ifadeleri, aniden dönüşür:

using MyAlias = System.Tuple<System.Linq.Expressions.Expression<System.Func<System.DateTime, object>>, System.Linq.Expressions.Expression<System.Func<System.TimeSpan, object>>>;

Güzel değil.


1
Sizin classihtiyaçlar bir ad (tanımlayıcı). usingBir sınıfın içinde belirttiğiniz gibi bir direktifiniz olamaz . Bir ad alanı düzeyinde, örneğin en dışta namespaceveya en içte olmalıdır namespace(ancak bir sınıf / arabirim / vb. İçinde olmamalıdır).
Jeppe Stig Nielsen

@JeppeStigNielsen Teşekkürler. usingDirektifleri yanlışlıkla yanlış yerleştirdim . Nasıl olmasını istediğim şekilde düzenledim. İşaret ettiğiniz için teşekkürler. Yine de akıl yürütme aynıdır.
Neo

4

Jeppe Stig Nielsen'in dediği gibi , bu konunun zaten harika cevapları var, ama bu oldukça belirgin incelikten de bahsetmeye değer olduğunu düşündüm.

using ad alanlarında belirtilen yönergeler, dışarıda belirtildikleri gibi tam olarak kalifiye olmaları gerekmediğinden daha kısa kodlar oluşturabilir.

Türleri çünkü Aşağıdaki örnek çalışır Foove Baraynı genel ad ikisi de, Outer.

Foo.cs kod dosyasını varsayalım :

namespace Outer.Inner
{
    class Foo { }
}

Ve Bar.cs :

namespace Outer
{
    using Outer.Inner;

    class Bar
    {
        public Foo foo;
    }
}

Bu, usingdirektifin dış ad alanını kısaca göz ardı edebilir :

namespace Outer
{
    using Inner;

    class Bar
    {
        public Foo foo;
    }
}

8
"Dış ad alanını atlayabileceğiniz" doğrudur, ancak bu yapmanız gerektiği anlamına gelmez. Bana göre bu, tam olarak nitelenmiş ad alanı adlarını zorlamak için direktifleri (@ Neo'nun cevabındaki gibi takma adlar dışında) kullanmanın neden ad alanının dışına çıkması gerektiğine dair başka bir argüman.
Keith Robertson

4

Karşılaştığım bir kırışıklık (diğer cevaplarda yer almıyor):

Bu ad alanlarına sahip olduğunuzu varsayalım:

  • Başka bir şey
  • Parent.Something.Other

Kullandığınızda using Something.Other dışında a'nınnamespace Parent , ilki (Something.Other) ifade eder.

Ancak içeride kullanırsanız bu ad alanı bildirimi kullanırsanız, ikincisine (Parent.Something.Other)!

Basit bir çözüm var: " global::" önekini ekleyin : docs

namespace Parent
{
   using global::Something.Other;
   // etc
}

2

Teknik nedenler cevaplarda tartışılıyor ve bence sonuçta kişisel tercihlere geliyor çünkü fark o kadar büyük değil ve her ikisi için de ödünler var. Visual Studio'nun .csdosya oluşturma varsayılan şablonu using, ad alanlarının dışındaki yönergeleri kullanır ;

Aşağıda , proje dosyasının kök dizinine dosya usingekleyerek, ad alanları dışındaki yönergeleri denetlemek için stylecop ayarlanabilir stylecop.json:

{
  "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
    "orderingRules": {
      "usingDirectivesPlacement": "outsideNamespace"
    }
  }
}

Bu yapılandırma dosyasını çözüm düzeyinde oluşturabilir ve yapılandırmayı tüm projelerinizde paylaşmak için 'Mevcut Bağlantı Dosyası' olarak projelerinize ekleyebilirsiniz.


2

Diğer cevapların kapsadığına inanmadığım bir başka incelik, aynı ada sahip bir sınıfınız ve ad alanınız olduğunda.

Ad alanının içinde içe aktarma yaptığınızda, sınıfı bulur. İçe aktarma ad alanının dışındaysa, içe aktarma yoksayılır ve sınıf ve ad alanının tam olarak nitelenmesi gerekir.

//file1.cs
namespace Foo
{
    class Foo
    {
    }
}

//file2.cs
namespace ConsoleApp3
{
    using Foo;
    class Program
    {
        static void Main(string[] args)
        {
            //This will allow you to use the class
            Foo test = new Foo();
        }
    }
}

//file2.cs
using Foo; //Unused and redundant    
namespace Bar
{
    class Bar
    {
        Bar()
        {
            Foo.Foo test = new Foo.Foo();
            Foo test = new Foo(); //will give you an error that a namespace is being used like a class.
        }
    }
}

-8

Bu eğer daha iyi bir uygulamadır varsayılan yani "seçeneğini kullanarak referansları ad ve olanları dışında olmalıdır kaynak çözümünde kullanılan" "Yeni eklenen referans" iyi bir uygulama size ad içine koymalıyız olmasıdır. Bu, hangi referansların eklendiğini ayırt etmektir.


6
Hayır, aslında bu kötü bir fikir. Yerel olarak kapsam dahilinde ve genel olarak kapsam dahilinde olmak üzere, konumu yeni eklenenler ya da eklenmedikleri yönergelerine dayandırmamalısınız. Bunun yerine, zirveye çıkması gereken BCL referansları hariç, bunları alfabetikleştirmek iyi bir uygulamadır.
Abel
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.