Khi nào tạo ngoại lệ tùy chỉnh trong C #


9

Tôi đang viết một lớp để giao diện với một thiết bị phần cứng đơn giản qua cổng COM. Thiết bị có thể được cấu hình để sử dụng các chế độ khác nhau, vì vậy lớp của tôi có một SetOperatingModechức năng, có một enumloại UsbDeviceMode. Nó trông giống như thế này:

class UsbDevice
{
    public void SetOperatingMode(UsbDeviceMode mode)
    { 
     byte[] buffer = new byte[4];
     buffer[0] = 0x5A;
     buffer[1] = 0x02;
     buffer[2] = (byte)mode;
     buffer[3] = 0x00; //IO_TYPE is always 0 in this case.

     _port.Write(buffer, 0, 4);
     int read = _port.Read(buffer, 0, 2);
     bool successfulSet = (read == 2 && buffer[0] == 0xFF && buffer[1] == 0x00);
    }
}

enum UsbDeviceMode
{
  IO_MODE = 0x00,
  IO_CHANGE = 0x10,
  I2C_S_20KHZ = 0x20,
  I2C_S_50KHZ = 0x30,
  I2C_S_100KHZ = 0x40,
  I2C_S_400KHZ = 0x50,
  I2C_H_100KHZ = 0x60,
  I2C_H_400KHZ = 0x70,
  I2C_H_1000KHZ = 0x80,
  SPI_MODE = 0x90,
  SERIAL = 0x01
};

Có khả năng khác biệt là hoạt động này có thể thất bại do bất kỳ lý do nào: Cổng COM có thể không còn tồn tại, thiết bị có thể bị khóa hoặc thất bại hoặc vì lý do nào đó, hoạt động không thành công.

Một thất bại sẽ là bất ngờ, nhưng không phải là hiếm. Có hai chế độ thất bại riêng biệt: Cổng COM đưa ra một ngoại lệ ( TimeoutExceptionInvalidOperationExceptionlà chế độ được mong đợi). Hoặc tôi có thể đọc lại một chỉ báo lỗi thiết bị.

Trong mọi trường hợp, nếu SetOperatingMode()thất bại, thì thiết bị hoặc giao tiếp bị hỏng theo cách nào đó và lớp này không thể làm bất cứ điều gì về nó.

Tôi có 2 câu hỏi:

  1. Tôi có nên "ném trước" InvalidOperationExceptionnếu cổng bị đóng không? Từ tài liệu MSDN, SerialPort.WriteSerialPortđọc sẽ ném nếu cổng được đóng. Tôi có thể kiểm tra xem ở trên cùng của hàm, hoặc tôi có thể để _port.Write()nó ném.
  2. Nếu có một loại ngoại lệ hoàn toàn mới ném khi successfulSetfalse? Nếu successfulSetfalse, không có gì mà lớp này có thể làm. Nên có một số loại SetOperatingModeFailedExceptionngoại lệ để phân biệt giữa cổng COM bị lỗi hoặc thiết bị bị lỗi? Có vẻ khá tốn thời gian để tạo ra một lớp ngoại lệ chỉ cho một điểm này.

Câu trả lời:


10

Sử dụng một ngoại lệ tùy chỉnh khi bạn muốn người dùng có thể phân biệt theo chương trình giữa các điều kiện lỗi nhất định. Nếu tình huống đó không tồn tại, bạn có thể ném ngoại lệ "chung" hơn và tránh tạo lớp ngoại lệ tùy chỉnh.

Trong trường hợp cụ thể của SetOperatingMode()ví dụ của bạn , trừ khi bạn cần gọi ra những cách cụ thể mà cuộc gọi phương thức này có thể thất bại, tốt hơn hết là bạn nên sử dụng một ngoại lệ chung hơn. Nói cách khác, nếu bạn có ý định ném SetOperatingModeFailedExceptionngoại lệ là kết quả có thể của việc gọi SetOperatingMode(), nhưng không phân biệt được về mặt lập trình loại lỗi hoạt động nào xảy ra, thì bạn có thể phân phối với việc tạo ngoại lệ tùy chỉnh (vì đó là trường hợp duy nhất có thể xảy ra ném), và chỉ cần ném một cái InvalidOperationException, có lẽ là ngoại lệ gần nhất hiện có.

Nếu bạn vẫn muốn tạo một ngoại lệ tùy chỉnh, hãy tạo một ngoại lệ có thể sử dụng lại qua các phương thức khác nhau, như OperationFailedException.


2

Tạo một lớp là dễ dàng. Đó không phải là một quá trình tốn thời gian. Mã gỡ lỗi mà che giấu các vấn đề là khó khăn. Và tốn thời gian.

Khi quyết định tạo ra một ngoại lệ hay không là câu hỏi bạn nên tự hỏi mình là "hành vi này có bình thường không, hành vi dự kiến ​​hay hành vi này là đặc biệt".

Trong trường hợp này, hành vi dự kiến ​​là chế độ vận hành luôn được đặt. Do đó, tôi sẽ đề xuất rằng các ngoại lệ cần phải được ném. Tôi sẽ cho phép bất kỳ trường hợp ngoại lệ từ bong bóng hoạt động viết lên. Tôi cũng sẽ tạo SetOperatingModeFailedException nếu dòng cuối cùng cho thấy có lỗi xảy ra.

Trong trường hợp này, phương thức của bạn thực sự chỉ có trách nhiệm cố gắng thiết lập chế độ vận hành. Nó không có trách nhiệm quản lý kết nối. Đó là trách nhiệm của người khác và nếu nó không được thực hiện đúng cách, một ngoại lệ sẽ được đưa ra.


Bạn dường như đã hiểu lầm những gì anh ấy yêu cầu. Anh ta nên sử dụng một trong các loại ngoại lệ hiện có, hoặc tự lăn?
Robert Harvey

1
Thật ra tôi đã trả lời câu hỏi của anh ấy. "Tôi sẽ cho phép bất kỳ trường hợp ngoại lệ từ bong bóng hoạt động viết lên." (tức là đừng bận tâm kiểm tra xem cổng có được mở không) và "tạo SetOperatingModeFailedException".
Stephen

1
Pfft. Một ngoại lệ tùy chỉnh là không cần thiết. Phương pháp nào có thể ném ngoại lệ, ngoại trừ bất kỳ cái nào bạn chọn? Làm thế nào để SetOperatingModeFailedException thêm bất kỳ giá trị nào ngoài, giả sử, UnlimitedOperationException? Không có ngoại lệ nào cho bạn biết lý do thất bại xảy ra hoặc cung cấp cho bạn cách phản hồi theo chương trình dựa trên loại ngoại lệ được đưa ra. Và việc tạo các lớp Exception mới không phải là miễn phí .
Robert Harvey

1
Nó có giá trị gì? Nó bổ sung nhiều giá trị khi được ghi chép đúng cách. Nó nói rằng vấn đề cụ thể này đã xảy ra. Không rõ ràng rằng mã cuộc gọi có thể phục hồi từ lỗi này.
Stephen

Bạn có thể cung cấp một thông báo lỗi chi tiết trong bất kỳ trường hợp ngoại lệ nào bạn ném. Trừ khi bạn có kế hoạch sử dụng các ngoại lệ cụ thể để cung cấp điều khiển theo chương trình cho người gọi, tôi nghĩ việc tạo một ngoại lệ tùy chỉnh là một sự lãng phí thời gian. Đừng hiểu ý tôi, hãy đọc , trong đó có nội dung "Tạo ngoại lệ do người dùng xác định nếu bạn muốn người dùng có thể phân biệt được lập trình giữa một số điều kiện lỗi."
Robert Harvey
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.