Konvensi penamaan C # untuk enum dan properti yang cocok

93

Saya sering menemukan diri saya menerapkan kelas yang mempertahankan beberapa jenis properti status sendiri sebagai enum: Saya memiliki Status enum dan SATU properti Status tipe Status. Bagaimana cara mengatasi konflik nama ini?

public class Car
{
  public enum Status
  {
    Off,
    Starting,
    Moving
  };

  Status status = Status.Off;

  public Status Status // <===== Won't compile =====
  {
    get { return status; }
    set { status = value; DoSomething(); }
  }
}

Jika Status enum umum untuk jenis yang berbeda, saya akan meletakkannya di luar kelas dan masalahnya akan terpecahkan. Tetapi Status hanya berlaku untuk Mobil sehingga tidak masuk akal untuk mendeklarasikan enum di luar kelas.

Konvensi penamaan apa yang Anda gunakan dalam kasus ini?

NB: Pertanyaan ini sebagian diperdebatkan dalam komentar dari jawaban pertanyaan ini . Karena ini bukan pertanyaan utama , maka tidak banyak terlihat.

EDIT: Filip Ekberg menyarankan solusi IMO yang sangat baik untuk kasus khusus 'Status'. Namun saya akan tertarik untuk membaca tentang solusi di mana nama enum / properti berbeda, seperti dalam jawaban Michael Prewecki .

EDIT2 (Mei 2010): Solusi favorit saya adalah menjumlahkan nama jenis enum, seperti yang disarankan oleh Chris S. Menurut pedoman MS, ini harus digunakan hanya untuk enum bendera. Tapi aku semakin menyukainya. Saya sekarang menggunakannya untuk enum biasa juga.

Serge Wautier
sumber
1
Saya tidak berpikir ada banyak solusi yang baik untuk ini jika Anda ingin enum bersarang di dalam kelas Anda. Saya sebenarnya lebih suka memiliki enum yang terpisah maka itu tidak menimbulkan masalah, tetapi saya dapat melihat poin Anda secara filosofis tentang keinginan untuk menyusunnya.
Craig Shearer

Jawaban:

32

Saya akan menambahkan 1 euro saya ke diskusi tetapi mungkin tidak menambahkan sesuatu yang baru.

Solusi yang jelas adalah memindahkan Status menjadi Enum bersarang. Sebagian besar .NET enum (kecuali mungkin beberapa di namespace Windows.Forms) tidak bersarang dan membuatnya mengganggu digunakan untuk pengembang yang mengonsumsi API Anda, harus mengawali nama kelas.

Satu hal yang belum disebutkan adalah bahwa enum flag menurut pedoman MSDN harus berupa kata benda jamak yang mungkin sudah Anda ketahui (Status adalah enum sederhana sehingga kata benda tunggal harus digunakan).

State (enum disebut States) adalah vocative, "Status" adalah nominatif dari kata benda yang bahasa Inggris seperti kebanyakan bahasa kita serap dari bahasa Latin. Vocative adalah nama kata benda untuk kondisinya dan nominatif adalah subjek dari kata kerja.

Jadi dengan kata lain saat mobil bergerak , itulah kata kerjanya - bergerak adalah statusnya. Tapi mobilnya tidak mati, mesinnya mati. Juga tidak menyala, mesin tidak (Anda mungkin memilih contoh di sini jadi ini mungkin tidak relevan).

public class Car
{
  VehicleState _vehicleState= VehicleState.Stationary;

  public VehicleState VehicleState 
  {
    get { return _vehicleState; }
    set { _vehicleState = value; DoSomething(); }
  }
}

public enum VehicleState
{
    Stationary, Idle, Moving
}

Negara adalah kata benda yang digeneralisasikan, bukankah lebih baik untuk menggambarkan keadaan yang dimaksud? Seperti yang saya lakukan di atas

Contoh tipe juga dalam pandangan saya tidak merujuk ke tipe pembaca, tetapi database-nya. Saya lebih suka jika Anda mendeskripsikan produk database pembaca yang belum tentu relevan dengan jenis pembaca (misalnya, jenis pembaca mungkin hanya maju, disimpan dalam cache, dan sebagainya). Begitu

reader.Database = Databases.Oracle;

Pada kenyataannya ini tidak pernah terjadi karena mereka diimplementasikan sebagai driver dan rantai warisan alih-alih menggunakan enum, itulah sebabnya baris di atas tidak terlihat alami.

Chris S
sumber
24
Pemahaman saya adalah bahwa flag harus dibuat jamak, bukan enum sederhana.
Serge Wautier
8
mengenai pemindahan enum keluar dari kelas, saya belum mengerti mengapa CarState lebih nyaman daripada Car.State. Namun, saya tidak memahami sisi positif mendapatkan enum dari kelas ketika enum ini hanya menjelaskan perilaku kelas ini.
Serge Wautier
Saya seharusnya menulis frasa kata benda seperti FileOptions, bukan hanya kata benda, saya telah memperbarui jawabannya. Saya kira classname.Enum hanyalah sebuah preferensi - Saya tidak dapat menemukan contoh apa pun dalam kerangka kerja yang akhirnya saya salin.
Chris S
Meskipun MS mengatakan bahwa jamak harus disimpan untuk bendera, seiring waktu, saya semakin menyukai solusi itu. Sekarang saya menggunakannya untuk enum juga. Oleh karena itu saya berubah pikiran dan menerima jawaban Anda, bukan Filip.
Serge Wautier
1
Saya tahu saya terlambat 1 1/2 tahun di sini, tetapi public class EngineStateharus menjadi public enum EngineStatecontoh, bukan?
David Murdoch
36

Definisi dari "Off", "Starting" dan "Moving" adalah apa yang saya sebut sebagai "State". Dan ketika Anda menyiratkan bahwa Anda menggunakan "Status", itu adalah "Status" Anda. Begitu!

public class Car
{
  public enum State
  {
    Off,
    Starting,
    Moving
  };

  State state = State.Off;

  public State Status
  {
    get { return state ; }
    set { state= value; DoSomething(); }
  }
}

Jika kita mengambil contoh lain dari yang dinyatakan di mana Anda ingin menggunakan kata "Type" seperti dalam kasus ini:

public class DataReader
{
    public enum Type
    {
        Sql,
        Oracle,
        OleDb
    }

    public Type Type { get; set; } // <===== Won't compile =====

}

Anda benar-benar perlu melihat bahwa ada perbedaan antara enum dan enum, bukan? Tetapi ketika membuat kerangka kerja atau berbicara tentang arsitektur, Anda perlu fokus pada kesamaan, ok mari kita temukan:

Ketika sesuatu diatur ke Status, itu didefinisikan sebagai Status "hal"

Contoh: Status Mobil dalam Status Berjalan, Status Berhenti, dan sebagainya.

Apa yang ingin Anda capai dalam contoh kedua adalah sebagai berikut:

myDataReader.Type = DataReader.Database.OleDb

Anda mungkin berpikir bahwa ini mengatakan bertentangan dengan apa yang telah saya khotbahkan kepada orang lain, bahwa Anda harus mengikuti standar. Tapi, Anda mengikuti standar! Kasus Sql adalah kasus khusus juga dan oleh karena itu membutuhkan solusi yang agak spesifik.

Namun, enum akan dapat digunakan kembali di dalam System.Dataruang Anda , dan itulah inti dari polanya.

Kasus lain untuk dilihat dengan "Type" adalah "Animal" dimana Type mendefinisikan Species.

public class Animal
    {
        public enum Type
        {
            Mammal,
            Reptile,
            JonSkeet
        }

        public Type Species{ get; set; }

    }

Ini mengikuti pola, Anda tidak perlu secara khusus "mengetahui" Objek untuk ini dan Anda tidak menentukan "AnimalType" atau "DataReaderType", Anda dapat menggunakan kembali enum di ruang nama pilihan Anda.

Filip Ekberg
sumber
1
Saya yakin nama "Status" hanyalah sebuah contoh. Bagaimana dengan situasi lain, ketika Anda tidak dapat mengandalkan Status / Status? Misalnya Jenis enum ...
Dan C.
2
@Filip: contoh Jenis Hewan menunjukkan dengan tepat apa yang saya maksud di komentar pertama, yaitu ini cukup banyak "penulisan ulang" dari enum. Menggunakan sinonim untuk enum dan nama properti membuat kode agak membingungkan, menurut saya.
Dan C.
1
Saya juga berpikir 'spesies' hanyalah penyusunan ulang jenis (untuk hewan dalam kasus ini).
LegendLength
2
Hanya mengganti nama tidak selalu bersih - pikirkan kelas untuk kartu remi misalnya, dengan Suit enum dan Suit properti - ganti nama menjadi apa sebenarnya? Bagaimanapun juga kikuk.
annakata
1
pendekatan ini menyebabkan kesalahpahaman dan mengacaukan kode
Boogier
9

Saya pikir masalah sebenarnya di sini adalah bahwa Status enum dienkapsulasi dalam kelas Anda, sedemikian rupa sehingga Car.Statusambigu baik untuk properti Statusmaupun enumStatus

Lebih baik lagi, letakkan enum Anda di luar kelas:

public enum Status
{
    Off,
    Starting,
    Moving
}

public class Car
{
    public Status Status
    { ... }
}

MEMPERBARUI

Karena komentar di bawah, saya akan menjelaskan desain saya di atas.

Saya salah satu yang tidak percaya bahwa enum atau kelas atau objek lain harus berada di dalam kelas lain, kecuali jika itu akan benar-benar pribadi dalam kelas itu. Ambil contoh di atas, misalnya:

public class Car
{
    public enum Status
    {...}
    ...
    public Status CarStatus { get; set;}
}

Sementara beberapa komentator akan berpendapat bahwa Status tidak memiliki arti apa pun di luar cakupan kelas Mobil, fakta bahwa Anda menyetel properti publik berarti ada bagian lain dari program yang akan menggunakan enum itu:

public Car myCar = new Car();
myCar.CarStatus = Car.Status.Off;

Dan yang bagi saya adalah kode bau. Jika aku akan melihat bahwa status luar dari Car, saya mungkin juga mendefinisikannya luar juga.

Karena itu, saya mungkin akan mengganti namanya menjadi:

public enum CarStatus
{...}

public class Car
{
    ...
    public CarStatus Status { get; set; }
}

Namun, jika enum itu akan digunakan di dalam dan hanya di dalam kelas mobil, maka saya baik-baik saja dengan menyatakan enum tersebut di sana.

Jon Limjap
sumber
Itu akan membuat Status mendunia, Anda mungkin ingin memilikinya di dalam area tertentu. "Status" untuk jenis lain seperti "Manusia" mungkin tidak memiliki "Mulai". Tetapi Anda harus mengikuti sebuah pola.
Filip Ekberg
Tidak, dia tepat. Enum dalam 99% kasus menggunakan kata yang sama yang ingin Anda gunakan untuk properti. Enum hanyalah sebuah bendera bernama sehingga tidak membahayakan jika tinggal di luar (tidak seperti kelas yang berisi logika)
Quibblesome
Jon, inilah tepatnya maksud saya: Enum Status berarti hanya tentang Mobil. Jenis objek yang sangat berbeda akan memiliki status yang sama sekali berbeda
Serge Wautier
mereka akan berada di ruang nama yang berbeda, jadi tidak masalah
Chris S
Penjelasan bahwa ingin melihatnya di luar mobil masuk akal. Tetapi dalam kasus saya, saya memiliki dua kelas, ORdan CR. Keduanya memiliki kumpulan statusnya sendiri, jadi ini bukan opsi untuk menentukannya di luar cakupannya sendiri.
akta02392
4

Saya tahu saran saya bertentangan dengan konvensi Penamaan .NET, tetapi saya secara pribadi mengawali enum dengan 'E' dan enum flag dengan 'F' (mirip dengan cara kita mengawali Antarmuka dengan 'I'). Saya benar-benar tidak mengerti mengapa ini bukan konvensi. Enums / Flags adalah kasus khusus seperti Antarmuka yang tidak akan pernah mengubah tipenya. Tidak hanya memperjelas apa itu, sangat mudah untuk mengetikkan intellisense karena awalan akan memfilter sebagian besar jenis / variabel / dll, dan Anda tidak akan mengalami bentrokan penamaan ini.

Dan itu juga akan memecahkan masalah lain di mana untuk contoh di WPF mereka menggunakan kelas statis seperti enum (misalnya FontWeights) yang memiliki contoh tipe yang telah ditentukan tetapi Anda tidak akan tahu jika Anda tidak mencarinya. Jika mereka hanya memberi awalan dengan 'E', yang harus Anda lakukan adalah mengetik karakter untuk menemukan kelas statis khusus ini.


sumber
4

Pembenci notasi Hongaria dan variannya terkutuk. Saya menggunakan konvensi sufiks enum dengan - tunggu - Enum. Akibatnya saya tidak pernah memiliki masalah yang Anda gambarkan, buang waktu mengkhawatirkan tentang apa yang harus memanggil mereka dan kode dapat dibaca dan deskriptif sendiri untuk boot.

public class Car
{
  public enum StatusEnum
  {
    Off,
    Starting,
    Moving
  };

  public StatusEnum Status { get; set; }

}
nathanchere.dll
sumber
9
Perlu diketahui bahwa konvensi Microsoft untuk Enumerasi Penamaan mengatakan: X JANGAN menggunakan akhiran "Enum" dalam nama jenis enum.
DavidRR
2
Karena konvensi Microsoft telah terbukti bertahan dalam ujian waktu.
nathanchere
2

Saya akan mengubah nama properti menjadi sesuatu seperti "CurrentStatus". Cepat dan mudah :)

TWith2Sugars
sumber
1

Saya sarankan untuk menambahkan "Option" ke nama tipe (atau Flag jika mengandung bit flag), yaitu tipe Car.StatusOption dan propertinya adalah Car.Status.

Dibandingkan dengan pluralisasi, ini menghindari benturan penamaan saat membuat koleksi dari jenis enum, di mana Anda biasanya ingin membuat jamak properti collection , bukan jenis enum .

Kristian Wedberg
sumber
0

Saya biasanya mengawali enum, misalnya CarStatus. Saya kira itu semua tergantung pada tim tempat Anda bekerja (jika mereka memiliki aturan / proses untuk hal semacam itu) dan penggunaan objek. Hanya 2 sen saya (:

Kieron
sumber
1
Itu benar-benar akan mematikan konvensi Penamaan yang memiliki MyObjectName di depan Status.
Filip Ekberg
Namespacing dari kelas seharusnya cukup untuk menangani hal ini
annakata