Haruskah arahan 'menggunakan' ada di dalam atau di luar namespace?


2062

Saya telah menjalankan StyleCop pada beberapa kode C #, dan terus melaporkan bahwa usingarahan saya harus berada di dalam namespace.

Apakah ada alasan teknis untuk menempatkan usingarahan di dalam daripada di luar namespace?


4
Kadang-kadang ada bedanya di mana Anda menempatkan usings: stackoverflow.com/questions/292535/linq-to-sql-designer-bug
gius

82
Hanya untuk referensi, ada implikasi lebih dari sekedar pertanyaan beberapa kelas per file, jadi jika Anda baru dengan pertanyaan ini, silakan terus membaca.
Charlie

3
@ user-12506 - ini tidak bekerja dengan baik di tim pengembangan sedang hingga besar di mana beberapa tingkat konsistensi kode diperlukan. Dan seperti disebutkan sebelumnya, jika Anda tidak memahami tata letak yang berbeda, Anda mungkin menemukan kasing tepi yang tidak berfungsi seperti yang Anda harapkan.
benPearce

35
Terminologi: Itu bukan using pernyataan ; mereka adalah using arahan . Sebuah usingpernyataan, di sisi lain, adalah struktur bahasa yang terjadi bersama dengan pernyataan lain dalam metode tubuh dll Sebagai contoh, using (var e = s.GetEnumerator()) { /* ... */ }adalah pernyataan yang longgar sama dengan var e = s.GetEnumerator(); try { /* ... */ } finally { if (e != null) { e.Dispose(); } }.
Jeppe Stig Nielsen

1
Jika ini tidak disebutkan oleh siapa pun, sebenarnya Microsoft juga merekomendasikan untuk memasukkan usingpernyataan di dalam namespacedeklarasi, di dalam panduan koding internal
user1451111

Jawaban:


2133

Sebenarnya ada perbedaan (halus) antara keduanya. Bayangkan Anda memiliki kode berikut di File1.cs:

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

Sekarang bayangkan seseorang menambahkan file lain (File2.cs) ke proyek yang terlihat seperti ini:

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

Kompiler mencari Outersebelum melihat usingarahan - arahan di luar namespace, jadi ia menemukan Outer.Mathbukan System.Math. Sayangnya (atau mungkin untungnya?), Tidak Outer.Mathmemiliki PIanggota, jadi File1 sekarang rusak.

Ini berubah jika Anda meletakkan bagian usingdalam deklarasi namespace Anda, sebagai berikut:

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

Sekarang kompiler mencari Systemsebelum mencari Outer, menemukan System.Math, dan semuanya baik-baik saja.

Beberapa orang akan berpendapat bahwa itu Mathmungkin nama yang buruk untuk kelas yang ditentukan pengguna, karena sudah ada satu di dalamnya System; intinya di sini adalah hanya bahwa ada adalah perbedaan, dan itu mempengaruhi rawatan kode Anda.

Menarik juga untuk dicatat apa yang terjadi jika Fooada dalam namespace Outer, bukan Outer.Inner. Dalam hal ini, menambahkan Outer.MathFile2 memecah File1 terlepas dari mana using. Ini menyiratkan bahwa kompiler mencari namespace terlampir paling dalam sebelum melihat usingarahan apa pun .


28
Ini adalah alasan yang jauh lebih baik untuk menggunakan pernyataan secara lokal daripada argumen multiple-namespaces-in-one-file Mark. Terutama karena kompilasi dapat dan akan mengeluh tentang bentrokan penamaan (lihat dokumentasi StyleCop untuk aturan ini (misalnya seperti yang diposting oleh Jared)).
David Schmitt

148
Jawaban yang diterima baik, tetapi bagi saya sepertinya alasan yang baik untuk menempatkan klausa penggunaan di luar namespace. Jika saya berada di luar namespace Outer. Saya berharap untuk menggunakan kelas Math dari Outer.Inner dan bukan System.Math.
Frank Wallis

7
Saya setuju dengan ini juga. Jawaban yang diterima benar karena secara teknis menjelaskan perbedaannya. Namun, satu atau kelas lain akan membutuhkan info eksplisit. Saya akan menilai ratehr memiliki "Matematika" untuk kelas lokal saya sendiri, dan "System.Math" merujuk ke kelas eksternal - bahkan jika System.Math digunakan sebagai "Matematika" sebelum Outer.Math ada. Ya, ini lebih banyak pekerjaan untuk memperbaiki namun banyak referensi yang sudah ada sebelumnya, tetapi itu juga bisa menjadi petunjuk bahwa mungkin Outer.Math harus memiliki nama yang berbeda!
mbmcavoy

13
Jawaban yang bagus, tetapi bagi saya sepertinya saya hanya ingin menempatkan non-framework menggunakan pernyataan secara lokal, dan menjaga framework menggunakan statement global. Adakah yang memiliki penjelasan lebih lanjut mengapa saya harus mengubah preferensi saya sepenuhnya? Juga dari mana asalnya, templat di VS2008 diletakkan di luar namespace?
Thymine

31
Saya pikir ini lebih merupakan konvensi penamaan yang buruk daripada mengubah tempat penggunaan Anda. Seharusnya tidak ada kelas yang disebut Matematika dalam solusi Anda
jDeveloper

454

Utas ini sudah memiliki beberapa jawaban yang bagus, tetapi saya merasa saya bisa membawa sedikit lebih detail dengan jawaban tambahan ini.

Pertama, ingat bahwa deklarasi namespace dengan titik, seperti:

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

sepenuhnya sama dengan:

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

Jika Anda mau, Anda bisa usingmengarahkan semua level ini. (Tentu saja, kami ingin memiliki usinghanya di satu tempat, tetapi akan sah menurut bahasa.)

Aturan untuk menyelesaikan jenis yang tersirat, dapat secara longgar dinyatakan seperti ini: Pertama mencari "lingkup" paling dalam untuk kecocokan, jika tidak ada yang ditemukan, keluar satu tingkat ke ruang lingkup berikutnya dan cari di sana, dan seterusnya , sampai kecocokan ditemukan. Jika pada tingkat tertentu lebih dari satu kecocokan ditemukan, jika salah satu jenis berasal dari rakitan saat ini, pilih yang itu dan keluarkan peringatan kompiler. Jika tidak, menyerah (kesalahan waktu kompilasi).

Sekarang, mari kita menjadi eksplisit tentang apa artinya ini dalam contoh nyata dengan dua konvensi utama.

(1) Dengan usings luar:

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;
    }
}

Dalam kasus di atas, untuk mengetahui apa jenisnya Ambiguous, pencarian dilakukan dalam urutan ini:

  1. Jenis bersarang di dalam C(termasuk jenis tersarang yang diwarisi)
  2. Ketik dalam namespace saat ini MyCorp.TheProduct.SomeModule.Utilities
  3. Jenis dalam namespace MyCorp.TheProduct.SomeModule
  4. Ketik dalam MyCorp.TheProduct
  5. Ketik dalam MyCorp
  6. Jenis dalam namespace nol (namespace global)
  7. Jenis dalam System, System.Collections.Generic, System.Linq, MyCorp.TheProduct.OtherModule, MyCorp.TheProduct.OtherModule.Integration, danThirdParty

Konvensi lainnya:

(2) Dengan usings di dalam:

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;
    }
}

Sekarang, cari jenisnya Ambiguousdengan urutan ini:

  1. Jenis bersarang di dalam C(termasuk jenis tersarang yang diwarisi)
  2. Ketik dalam namespace saat ini MyCorp.TheProduct.SomeModule.Utilities
  3. Jenis dalam System, System.Collections.Generic, System.Linq, MyCorp.TheProduct, MyCorp.TheProduct.OtherModule, MyCorp.TheProduct.OtherModule.Integration, danThirdParty
  4. Jenis dalam namespace MyCorp.TheProduct.SomeModule
  5. Ketik dalam MyCorp
  6. Jenis dalam namespace nol (namespace global)

(Perhatikan bahwa MyCorp.TheProductitu adalah bagian dari "3." dan karena itu tidak diperlukan antara "4." dan "5.".)

Komentar penutup

Tidak masalah jika Anda menempatkan usings di dalam atau di luar deklarasi namespace, selalu ada kemungkinan bahwa seseorang nanti menambahkan tipe baru dengan nama yang identik ke salah satu ruang nama yang memiliki prioritas lebih tinggi.

Juga, jika namespace bersarang memiliki nama yang sama dengan tipe, itu dapat menyebabkan masalah.

Itu selalu berbahaya untuk memindahkan usings dari satu lokasi ke lokasi lain karena hirarki pencarian berubah, dan jenis lain dapat ditemukan. Karena itu, pilih satu konvensi dan patuhi itu, sehingga Anda tidak perlu pernah memindahkan usings.

Templat Visual Studio, secara default, menempatkan usings di luar namespace (misalnya jika Anda membuat VS menghasilkan kelas baru dalam file baru).

Satu (kecil) keuntungan memiliki usings di luar adalah bahwa Anda kemudian dapat menggunakan arahan penggunaan untuk atribut global, misalnya, [assembly: ComVisible(false)]bukan [assembly: System.Runtime.InteropServices.ComVisible(false)].


46
Ini adalah penjelasan terbaik, karena menyoroti fakta bahwa posisi pernyataan 'menggunakan' adalah keputusan yang disengaja dari pengembang. Dalam kasus apa pun seseorang tidak boleh dengan ceroboh mengubah lokasi pernyataan 'menggunakan' tanpa memahami implikasinya. Karena itu aturan StyleCop hanya bodoh.
ZunTzu

194

Menempatkannya di dalam namespaces membuat deklarasi lokal ke namespace untuk file tersebut (jika Anda memiliki beberapa namespaces dalam file) tetapi jika Anda hanya memiliki satu namespace per file maka itu tidak membuat banyak perbedaan apakah mereka pergi ke luar atau di dalam namespace.

using ThisNamespace.IsImported.InAllNamespaces.Here;

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

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

namespace Namespace3
{ 
   using ThisNamespace.IsImported.InJustNamespace3;
}

namespaces memberikan pemisahan logis, bukan fisik (file).
Jowen

9
Tidak sepenuhnya benar bahwa tidak ada perbedaan; usingarahan dalam namespaceblok dapat merujuk ke ruang nama relatif berdasarkan namespaceblok terlampir .
ATAU Mapper

70
ya aku tahu. kami menetapkan bahwa dalam jawaban yang diterima pertanyaan ini lima tahun lalu.
Mark Cidade

59

Menurut Hanselman - Menggunakan Petunjuk dan Pemuatan Majelis ... dan artikel-artikel serupa lainnya secara teknis tidak ada perbedaan.

Preferensi saya adalah menempatkannya di luar ruang nama.


3
@ Chris M: uh ... tautan yang diposting di jawaban menunjukkan tidak ada manfaatnya masuk keluar, sebenarnya menunjukkan contoh yang memalsukan klaim yang dibuat di tautan yang Anda poskan ...
johnny

2
Ya saya tidak sepenuhnya membaca utas tetapi membeli ketika MVP mengatakan itu benar. Seorang pria menyangkal hal itu, menjelaskannya dan menunjukkan kodenya lebih jauh ... "IL yang dihasilkan oleh kompiler C # adalah sama dalam kedua kasus tersebut. Bahkan kompiler C # menghasilkan tidak ada yang sesuai dengan masing-masing menggunakan arahan. Menggunakan arahan adalah murni C # ism, dan mereka tidak memiliki arti untuk .NET itu sendiri (Tidak berlaku untuk menggunakan pernyataan tetapi itu adalah sesuatu yang sangat berbeda.) " Groups.google.com/group/wpf-disciples/msg/781738deb0a15c46
Chris McKee

84
Harap sertakan ringkasan tautan. Ketika tautan rusak (karena itu akan terjadi, diberikan waktu yang cukup), tiba-tiba sebuah jawaban dengan 32 upvotes hanya bernilai My style is to put them outside the namespaces.- hampir tidak ada jawaban sama sekali.
ANeves

11
Klaim di sini benar-benar salah ... ada perbedaan teknis dan kutipan Anda sendiri mengatakan demikian ... sebenarnya, itulah masalahnya. Harap hapus jawaban yang salah ini ... ada yang jauh lebih baik, dan akurat.
Jim Balter

53

Menurut Dokumentasi StyleCop:

SA1200: MenggunakanDirectivesMustBePlacedWithinNamespace

Penyebab AC # menggunakan arahan ditempatkan di luar elemen namespace.

Deskripsi Aturan Pelanggaran aturan ini terjadi ketika arahan menggunakan atau arahan using-alias ditempatkan di luar elemen namespace, kecuali file tersebut tidak mengandung elemen namespace.

Misalnya, kode berikut akan menghasilkan dua pelanggaran aturan ini.

using System;
using Guid = System.Guid;

namespace Microsoft.Sample
{
    public class Program
    {
    }
}

Namun, kode berikut tidak akan mengakibatkan pelanggaran apa pun terhadap aturan ini:

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

    public class Program
    {
    }
}

Kode ini akan dikompilasi dengan bersih, tanpa ada kesalahan kompiler. Namun, tidak jelas versi jenis Guid yang dialokasikan. Jika arahan penggunaan dipindahkan di dalam namespace, seperti yang ditunjukkan di bawah ini, kesalahan kompiler akan terjadi:

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");
        }
    }
}

Kode gagal pada kesalahan kompilator berikut, ditemukan pada baris yang berisi Guid g = new Guid("hello");

CS0576: Namespace 'Microsoft.Sample' berisi definisi yang bertentangan dengan alias 'Guid'

Kode tersebut membuat alias ke tipe System.Guid yang disebut Guid, dan juga membuat tipe sendiri yang disebut Guid dengan antarmuka konstruktor yang cocok. Kemudian, kode menciptakan turunan dari tipe Guid. Untuk membuat instance ini, kompiler harus memilih antara dua definisi Guid yang berbeda. Ketika directive alias menggunakan ditempatkan di luar elemen namespace, kompiler akan memilih definisi lokal Guid didefinisikan dalam namespace lokal, dan sepenuhnya mengabaikan directive alias menggunakan yang didefinisikan di luar namespace. Sayangnya, ini tidak jelas ketika membaca kode.

Ketika menggunakan-alias direktif diposisikan dalam namespace, kompiler harus memilih antara dua jenis Guid yang berbeda dan saling bertentangan, keduanya didefinisikan dalam namespace yang sama. Kedua tipe ini menyediakan konstruktor yang cocok. Kompiler tidak dapat membuat keputusan, sehingga menandai kesalahan kompiler.

Menempatkan menggunakan-alias direktif di luar namespace adalah praktik yang buruk karena dapat menyebabkan kebingungan dalam situasi seperti ini, di mana tidak jelas versi jenis mana yang benar-benar digunakan. Ini berpotensi menyebabkan bug yang mungkin sulit didiagnosis.

Menempatkan arahan-alias menggunakan dalam elemen namespace menghilangkan ini sebagai sumber bug.

  1. Banyak ruang nama

Menempatkan banyak elemen namespace dalam satu file umumnya adalah ide yang buruk, tetapi jika dan ketika ini dilakukan, itu adalah ide yang baik untuk menempatkan semua menggunakan arahan dalam setiap elemen namespace, daripada secara global di bagian atas file. Ini akan membatasi ruang nama secara ketat, dan juga akan membantu menghindari jenis perilaku yang dijelaskan di atas.

Penting untuk dicatat bahwa ketika kode telah ditulis dengan menggunakan arahan yang ditempatkan di luar namespace, harus berhati-hati ketika memindahkan arahan ini di dalam namespace, untuk memastikan bahwa ini tidak mengubah semantik kode. Seperti dijelaskan di atas, menempatkan arahan-alias menggunakan di dalam elemen namespace memungkinkan kompiler untuk memilih antara tipe yang saling bertentangan dengan cara yang tidak akan terjadi ketika arahan ditempatkan di luar namespace.

Cara Memperbaiki Pelanggaran Untuk memperbaiki pelanggaran aturan ini, pindahkan semua menggunakan arahan dan arahan menggunakan-alias di dalam elemen namespace.


1
@ Jared - seperti yang saya catat dalam jawaban saya, solusi / solusi pilihan saya adalah hanya memiliki satu kelas per file. Saya pikir ini adalah konvensi yang cukup umum.
benPearce

24
Memang, itu juga aturan StyleCop! SA1402: dokumen AC # hanya boleh berisi satu kelas di tingkat akar kecuali semua kelas parsial dan dari jenis yang sama. Menampilkan satu aturan dengan melanggar yang lain hanya menetes dengan saus yang salah.
Tugas

6
Terpilih karena menjadi jawaban pertama yang benar-benar menutupinya dari perspektif StyleCop. Secara pribadi saya suka nuansa visual usingdi luar namespace. Batin usingterlihat begitu buruk bagiku. :)
nawfal

2
Akhirnya jawaban yang bagus untuk pertanyaan itu. Dan komentar benPearce tidak relevan ... ini tidak ada hubungannya dengan jumlah kelas dalam file.
Jim Balter

35

Ada masalah dengan menempatkan pernyataan menggunakan di dalam namespace ketika Anda ingin menggunakan alias. Alias ​​tidak mendapat manfaat dari usingpernyataan sebelumnya dan harus sepenuhnya memenuhi syarat.

Mempertimbangkan:

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

    class MyClass
    {
    }
}

melawan:

using System;

namespace MyNamespace
{
    using MyAlias = DateTime;

    class MyClass
    {
    }
}

Ini dapat diucapkan secara khusus jika Anda memiliki alias bertele-tele seperti berikut ini (yang merupakan bagaimana saya menemukan masalah):

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

Dengan usingpernyataan di dalam namespace, tiba-tiba menjadi:

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

Tidak cantik.


1
Anda classmembutuhkan nama (pengidentifikasi). Anda tidak dapat memiliki usingarahan di dalam kelas seperti yang Anda tunjukkan. Itu harus di tingkat namespace, misalnya di luar terluar namespace, atau tepat di dalam terluar namespace(tetapi tidak di dalam kelas / antarmuka / dll.).
Jeppe Stig Nielsen

@JeppeStigNielsen Terima kasih. Saya salah menempatkan usingarahan secara keliru. Saya telah mengeditnya sesuai dengan yang saya inginkan. Terima kasih telah menunjukkan. Alasannya masih sama.
Neo

4

Sebagai Jeppe Stig Nielsen mengatakan , thread ini sudah memiliki jawaban yang besar, tapi saya pikir kehalusan agak jelas ini layak disebut juga.

using arahan yang ditentukan di dalam ruang nama dapat membuat kode lebih pendek karena tidak perlu sepenuhnya memenuhi syarat seperti ketika mereka ditentukan di luar.

Contoh berikut berfungsi karena tipe Foodan Barkeduanya di namespace global yang sama Outer,.

Anggap file kode Foo.cs :

namespace Outer.Inner
{
    class Foo { }
}

Dan Bar.cs :

namespace Outer
{
    using Outer.Inner;

    class Bar
    {
        public Foo foo;
    }
}

Itu bisa menghilangkan namespace luar dalam usingdirektif, singkatnya:

namespace Outer
{
    using Inner;

    class Bar
    {
        public Foo foo;
    }
}

8
Memang benar bahwa Anda "mungkin menghilangkan namespace luar," tetapi itu tidak berarti Anda harus melakukannya. Bagi saya, ini adalah argumen lain mengapa menggunakan arahan (selain alias seperti dalam jawaban @ Neo) harus pergi di luar namespace, untuk memaksa nama namespace yang sepenuhnya memenuhi syarat.
Keith Robertson

4

Satu kerutan yang saya temui (yang tidak tercakup dalam jawaban lain):

Misalkan Anda memiliki ruang nama ini:

  • Sesuatu. Lainnya
  • Induk. Sesuatu. Lainnya

Saat Anda menggunakan di using Something.Other luar a namespace Parent, itu mengacu pada yang pertama (Sesuatu. Lainnya).

Namun jika Anda menggunakannya di dalam deklarasi namespace itu, itu merujuk pada yang kedua (Parent. Sesuatu. Lainnya)!

Ada solusi sederhana: tambahkan global::awalan " ": docs

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

2

Alasan teknis dibahas dalam jawaban dan saya pikir itu pada preferensi pribadi pada akhirnya karena perbedaannya tidak begitu besar dan ada pengorbanan untuk keduanya. Template default Visual Studio untuk membuat .csfile menggunakan usingarahan di luar ruang nama misalnya

Orang dapat menyesuaikan stylecop untuk memeriksa usingarahan di luar ruang nama melalui menambahkan stylecop.jsonfile di root file proyek dengan yang berikut:

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

Anda dapat membuat file konfigurasi ini di tingkat solusi dan menambahkannya ke proyek Anda sebagai 'File Tautan yang Ada' untuk membagikan konfigurasi di semua proyek Anda juga.


2

Kehalusan lain yang saya tidak percaya telah tercakup oleh jawaban lain adalah ketika Anda memiliki kelas dan namespace dengan nama yang sama.

Ketika Anda memiliki impor di dalam namespace maka itu akan menemukan kelas. Jika impor di luar namespace maka impor akan diabaikan dan kelas dan namespace harus sepenuhnya memenuhi syarat.

//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

Ini adalah praktik yang lebih baik jika standar yang digunakan yaitu " referensi " yang digunakan dalam solusi sumber Anda harus berada di luar ruang nama dan yang "baru ditambahkan referensi" adalah praktik yang baik adalah Anda harus meletakkannya di dalam namespace. Ini untuk membedakan referensi apa yang ditambahkan.


6
Tidak, sebenarnya itu ide yang buruk. Anda tidak boleh mendasarkan lokasi antara cakupan lokal dan cakupan global menggunakan arahan pada kenyataan bahwa mereka baru ditambahkan atau tidak. Sebaliknya, itu adalah praktik yang baik untuk mengabjadkannya, kecuali untuk referensi BCL, yang harusnya di atas.
Abel
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.