Quy ước đặt tên trong C # cho enum và thuộc tính phù hợp


93

Tôi thường thấy mình đang triển khai một lớp duy trì một số loại thuộc tính trạng thái riêng như một enum: Tôi có một enum Trạng thái và MỘT thuộc tính Trạng thái của loại Trạng thái. Tôi nên giải quyết xung đột tên này như thế nào?

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

Nếu Enum Trạng thái phổ biến với các loại khác nhau, tôi sẽ đặt nó bên ngoài lớp và vấn đề sẽ được giải quyết. Nhưng Trạng thái chỉ áp dụng cho Xe hơi do đó không có ý nghĩa gì khi khai báo enum bên ngoài lớp.

Bạn sử dụng quy ước đặt tên nào trong trường hợp này?

NB: Câu hỏi này đã được tranh luận một phần trong các bình luận về câu trả lời của câu hỏi này . Vì nó không phải câu hỏi chính , nó không được hiển thị nhiều.

CHỈNH SỬA: Filip Ekberg đề xuất một giải pháp IMO tuyệt vời cho trường hợp cụ thể của 'Trạng thái'. Tuy nhiên, tôi sẽ rất thú vị khi đọc về các giải pháp mà tên của enum / property khác nhau, như trong câu trả lời của Michael Prewecki .

EDIT2 (tháng 5 năm 2010): Giải pháp yêu thích của tôi là đa dạng hóa tên loại enum, theo đề xuất của Chris S. Theo hướng dẫn của MS, điều này chỉ nên được sử dụng cho cờ enum. Nhưng tôi ngày càng thích nó hơn. Bây giờ tôi cũng sử dụng nó cho enums thông thường.


1
Tôi không nghĩ rằng có nhiều giải pháp tốt cho việc này nếu bạn muốn có enum được lồng vào bên trong lớp của mình. Tôi thực sự thích để enum riêng biệt thì nó không có vấn đề gì, nhưng tôi có thể thấy quan điểm của bạn một cách triết lý về việc muốn lồng nó vào.
Craig Shearer

Câu trả lời:


32

Tôi sẽ thêm 1 euro của mình vào cuộc thảo luận nhưng nó có thể không thêm bất cứ điều gì mới.

Giải pháp rõ ràng là chuyển Status ra khỏi Enum lồng nhau. Hầu hết các enum .NET (ngoại trừ có thể một số trong không gian tên Windows.Forms) không được lồng vào nhau và nó gây khó chịu khi sử dụng cho nhà phát triển sử dụng API của bạn, phải đặt tiền tố tên lớp.

Một điều chưa được đề cập là cờ enum theo hướng dẫn của MSDN phải là danh từ đa dạng mà bạn có thể đã biết (Trạng thái là một enum đơn giản nên danh từ số ít nên được sử dụng).

State (tiếng Anh gọi là States) là cách xưng hô, "Status" là danh từ chỉ danh từ mà người Anh cũng như hầu hết ngôn ngữ của chúng ta tiếp thu từ tiếng Latinh. Xưng hô là những gì bạn đặt tên cho một danh từ cho điều kiện của nó và danh từ là chủ ngữ của động từ.

Vì vậy, nói cách khác khi chiếc xe đang chuyển động , đó là động từ - chuyển động là trạng thái của nó. Nhưng chiếc xe không nổ, động cơ của nó. Nó cũng không khởi động, động cơ cũng không (có thể bạn đã chọn một ví dụ ở đây nên điều này có thể không liên quan).

public class Car
{
  VehicleState _vehicleState= VehicleState.Stationary;

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

public enum VehicleState
{
    Stationary, Idle, Moving
}

State là một danh từ khái quát như vậy sẽ không tốt hơn nếu mô tả nó đang đề cập đến trạng thái nào? Như tôi đã làm ở trên

Ví dụ về kiểu cũng trong chế độ xem của tôi không đề cập đến kiểu người đọc mà là cơ sở dữ liệu của nó. Tôi sẽ thích nó hơn nếu bạn mô tả sản phẩm cơ sở dữ liệu của trình đọc mà không nhất thiết phải liên quan đến loại trình đọc (ví dụ: loại trình đọc có thể chỉ được chuyển tiếp, được lưu trong bộ nhớ cache, v.v.). Vì thế

reader.Database = Databases.Oracle;

Trong thực tế, điều này không bao giờ xảy ra vì chúng được triển khai dưới dạng trình điều khiển và chuỗi kế thừa thay vì sử dụng enum, đó là lý do tại sao dòng trên trông không tự nhiên.


24
Sự hiểu biết của tôi là cờ nên được đa dạng hóa, không phải là enums đơn giản.
Serge Wautier,

8
về việc di chuyển enums ra khỏi lớp, tôi vẫn chưa hiểu tại sao CarState lại tiện lợi hơn Car.State. Tuy nhiên, tôi không hiểu mặt tích cực của việc lấy một enum ra khỏi một lớp khi enum này chỉ mô tả hành vi của lớp này.
Serge Wautier,

Tôi lẽ ra nên viết các cụm danh từ như FileOptions không chỉ là danh từ, tôi đã cập nhật câu trả lời. Tôi cho rằng classname.Enum chỉ là một tùy chọn - Tôi không thể tìm thấy bất kỳ ví dụ nào trong khuôn khổ mà tôi muốn sao chép.
Chris S

Mặc dù MS nói rằng nên giữ số nhiều cho cờ, theo thời gian, tôi ngày càng thích giải pháp đó. Bây giờ tôi cũng sử dụng nó cho enums. Do đó tôi đã đổi ý và chấp nhận câu trả lời của bạn thay vì của Filip.
Serge Wautier

1
Tôi biết tôi đã trễ 1 năm rưỡi ở đây, nhưng public class EngineStatenên public enum EngineStateở trong ví dụ, phải không?
David Murdoch

36

Định nghĩa của "Tắt", "Bắt đầu" và "Di chuyển" là những gì tôi sẽ gọi là "Trạng thái". Và khi bạn ngụ ý rằng bạn đang sử dụng một "Trạng thái", thì đó chính là "Trạng thái" của bạn. Vì thế!

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

  State state = State.Off;

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

Nếu chúng tôi lấy một ví dụ khác từ ví dụ đã nêu nơi bạn muốn sử dụng từ "Loại" trong trường hợp này:

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

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

}

Bạn thực sự cần phải thấy rằng có sự khác biệt giữa enums và enums, phải không? Nhưng khi tạo một khuôn khổ hoặc nói về kiến ​​trúc, bạn cần tập trung vào các mô phỏng, hãy tìm chúng:

Khi một thứ gì đó được đặt thành Trạng thái, nó được định nghĩa là Trạng thái "mọi thứ"

Ví dụ: Trạng thái Xe đang ở Trạng thái Đang chạy, Trạng thái Đã dừng, v.v.

Những gì bạn muốn làm rõ trong ví dụ thứ hai là phần nào sau:

myDataReader.Type = DataReader.Database.OleDb

Bạn có thể nghĩ rằng điều này nói ngược lại những gì tôi đã giảng cho người khác, rằng bạn cần phải tuân theo một tiêu chuẩn. Nhưng, bạn đang tuân theo một tiêu chuẩn! Trường hợp Sql cũng là một trường hợp cụ thể và do đó cần một giải pháp cụ thể.

Tuy nhiên, enum sẽ có thể tái sử dụng trong System.Datakhông gian của bạn , và đó là tất cả những gì về mô hình.

Một trường hợp khác cần xem xét với "Loại" là "Động vật" trong đó Loại xác định Loài.

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

        public Type Species{ get; set; }

    }

Đây là theo một mẫu, bạn không cần phải "biết" Đối tượng một cách cụ thể và bạn không chỉ định "AnimalType" hoặc "DataReaderType", bạn có thể sử dụng lại các enums trong không gian tên mà bạn chọn.


1
Tôi tin rằng tên "Trạng thái" chỉ là một ví dụ. Còn những tình huống khác, khi bạn không thể dựa vào Trạng thái / Trạng thái? Ví dụ như một loại enum ...
Dan C.

Bạn có thể vui lòng cung cấp một tình huống ví dụ cho điều đó? ốm cố gắng để mở rộng câu trả lời của tôi theo là tốt mà :)
Filip Ekberg

2
@Filip: mẫu Animal Type chỉ ra chính xác ý tôi trong nhận xét đầu tiên, tức là đây là "bản ghi lại" khá nhiều của enum. Tôi nghĩ rằng việc sử dụng các từ đồng nghĩa với enum và tên thuộc tính làm cho mã hơi khó hiểu.
Dan C.

1
Tôi cũng nghĩ rằng 'loài' chỉ là một bản ghi lại của loại (đối với động vật trong trường hợp này).
LegendLength

2
Đơn giản là đổi tên không phải lúc nào cũng sạch sẽ - hãy nghĩ đến một lớp cho một thẻ chơi bài, ví dụ như với Bộ đồ enum và Bộ đồ thuộc tính - đổi tên chính xác là gì? Vụng về cả hai cách.
annakata

9

Tôi nghĩ vấn đề thực sự ở đây là Trạng thái enum được đóng gói trong lớp của bạn, điều Car.Statusnày không rõ ràng đối với cả thuộc tính Statusvà enumStatus

Tốt hơn, hãy đặt enum của bạn bên ngoài lớp học:

public enum Status
{
    Off,
    Starting,
    Moving
}

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

CẬP NHẬT

Do các bình luận bên dưới, tôi sẽ giải thích thiết kế của tôi ở trên.

Tôi là người không tin rằng enums hoặc các lớp hoặc bất kỳ đối tượng nào khác nên nằm bên trong một lớp khác, trừ khi nó hoàn toàn riêng tư trong lớp đó. Lấy ví dụ trên, chẳng hạn:

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

Trong khi một số người bình luận sẽ tranh luận rằng Trạng thái không có bất kỳ ý nghĩa nào ngoài phạm vi của Class Car, thực tế là bạn đang đặt thuộc tính công cộng có nghĩa là có các phần khác của chương trình sẽ sử dụng enum đó:

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

đó đối với tôi là một mùi mã. Nếu tôi sẽ nhìn vào đó tình trạng bên ngoài của Car, tôi cũng có thể định nghĩa nó bên ngoài là tốt.

Như vậy, tôi có thể sẽ chỉ đổi tên nó thành:

public enum CarStatus
{...}

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

Tuy nhiên, nếu enum đó sẽ được sử dụng trong và chỉ trong lớp xe hơi, thì tôi vẫn ổn với việc khai báo enum ở đó.


Điều đó sẽ làm cho Trạng thái trở nên toàn cầu, bạn có thể muốn có nó ngay trong một khu vực cụ thể. "Trạng thái" cho các loại khác như "Con người" có thể không có "Đang bắt đầu". Nhưng bạn nên làm theo một khuôn mẫu.
Filip Ekberg

Không, anh ấy đúng chỗ. Trong 99% trường hợp, enum chính là từ mà bạn muốn sử dụng cho thuộc tính. Một enum chỉ là một lá cờ đặt tên như vậy nó làm hại chút ở bên ngoài sống (không giống như các lớp học có chứa logic)
Quibblesome

Jon, đây chính xác là quan điểm của tôi: tình trạng Trạng thái chỉ liên quan đến Xe hơi. Hoàn toàn loại khác nhau của các đối tượng sẽ có trạng thái hoàn toàn khác nhau
Serge WAUTIER

họ sẽ có trong không gian tên khác nhau mặc dù, vì vậy nó sẽ không quan trọng
Chris S

Lời giải thích rằng muốn nhìn nó bên ngoài Xe hơi có ý nghĩa. Nhưng trong trường hợp của tôi, tôi có hai lớp, ORCR. Cả hai đều có tập hợp trạng thái riêng, vì vậy không phải là tùy chọn để xác định chúng bên ngoài phạm vi của riêng chúng.
deed02392,

4

Tôi biết đề xuất của mình đi ngược lại quy ước Đặt tên .NET, nhưng cá nhân tôi đặt tiền tố enum bằng 'E' và cờ enum bằng 'F' (tương tự như cách chúng tôi đặt tiền tố Giao diện bằng 'I'). Tôi thực sự không hiểu tại sao đây không phải là quy ước. Enums / Flags là một trường hợp đặc biệt như Interfaces sẽ không bao giờ thay đổi kiểu của chúng. Nó không chỉ làm rõ nó là gì, rất dễ dàng nhập intellisense vì tiền tố sẽ lọc hầu hết các kiểu / biến / vv khác và bạn sẽ không gặp phải những xung đột về tên này.

Và điều đó cũng sẽ giải quyết một vấn đề khác trong đó đối với các ví dụ trong WPF, họ sử dụng các lớp tĩnh như enums (ví dụ: FontWeights) có các thể hiện kiểu được xác định trước nhưng bạn sẽ không biết nếu bạn không tìm kiếm nó. Nếu họ chỉ bắt đầu bằng 'E', tất cả những gì bạn phải làm là gõ ký tự để tìm các lớp tĩnh đặc biệt này.


4

Những kẻ ghét ký hiệu Hungary và các biến thể của nó thật đáng nguyền rủa. Tôi sử dụng một quy ước về hậu tố enums với - chờ nó - Enum. Do đó, tôi không bao giờ gặp vấn đề như bạn mô tả, lãng phí thời gian lo lắng về việc gọi chúng là gì và mã có thể đọc được và tự mô tả để khởi động.

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

  public StatusEnum Status { get; set; }

}

9
Xin lưu ý rằng các quy ước của Microsoft về Danh sách Đặt tên nói: X KHÔNG sử dụng hậu tố "Enum" trong các tên kiểu enum.
DavidRR

2
Bởi vì các quy ước của Microsoft đã được chứng minh là đứng vững trước thử thách của thời gian.
nathanchere

2

Tôi muốn thay đổi tên của thuộc tính thành một cái gì đó giống như "CurrentStatus". Nhanh chóng dễ dàng :)


1

Tôi đề nghị thêm "Option" vào tên kiểu (hoặc Flag nếu nó chứa cờ bit), tức là kiểu là Car.StatusOption và thuộc tính là Car.Status.

So với pluralizing, tránh được điều này đặt tên va chạm khi tạo bộ sưu tập của các loại enum, nơi bạn thường muốn pluralize bộ sưu tập bất động sản , không phải là enum loại .


0

Tôi thường đặt trước các enum, ví dụ như CarStatus. Tôi cho rằng tất cả phụ thuộc vào nhóm bạn đang làm việc (nếu họ có bất kỳ quy tắc / quy trình nào cho loại điều đó) và việc sử dụng các đối tượng. Chỉ 2 xu của tôi (:


1
Điều đó thực sự sẽ giết chết quy ước Đặt tên có MyObjectName trước Trạng thái.
Filip Ekberg

các namespacing từ lớp nên là đủ để đối phó với điều này anyway
annakata
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.