2009-02-11 32 views
10

Tôi chỉ viết một câu lệnh if trong dòngĐây có phải là cách sử dụng tốt của ExtensionMethod không?

if (value == value1 || value == value2 || value == value3 || value == value4) 
    //do something 

và nó làm phiền tôi mà tôi luôn phải lặp lại 'giá trị ==' phần. Theo tôi, điều này là không phục vụ mục đích nào khác ngoài việc làm cho nó khó đọc.

tôi viết ExtensionMethod sau đó nên làm cho kịch bản trên dễ đọc hơn:

public static bool IsEqualToAny<T>(this T value, params T[] objects) 
{ 
    return objects.Contains(value); 
} 

Bây giờ tôi chỉ có thể viết

if (value.IsEqualToAny(value1, value2, value3, value4)) 
    //do something 

Đây có phải là một cách sử dụng tốt của một ExtensionMethod?

EDIT:

Cảm ơn tất cả các câu trả lời tuyệt vời. Đối với hồ sơ: Tôi đã giữ phương pháp. Trong khi gợi ý rằng bạn chỉ có thể sử dụng new []{value1,value2,value3,value4}.Contains(value) là sự thật, tôi chỉ đơn giản là thích đọc loại này của câu lệnh if từ trái sang phải (nếu giá trị này tương đương với bất kỳ của các thay vì nếu những giá trị này chứa giá trị này). Có thêm một phương pháp hiển thị trong intellisense trên mỗi đối tượng không phải là một vấn đề đối với tôi.

Trả lời

4

Bạn chưa thêm chức năng chỉ hữu ích cho ứng dụng hoặc ngữ cảnh cụ thể, tiện ích mở rộng của bạn được đặt tên rõ ràng và hành vi hiển nhiên mà không cần phải xem xét triển khai.

Câu trả lời là "Có, nó là"

1

Có vẻ tốt với tôi, mặc dù có vẻ hơi độc đáo một chút.

1

Có vẻ khá công bằng, nhưng tôi sẽ lùi lại một bước. Bạn có thể đặt bất kỳ ý nghĩa kinh doanh nào trong so sánh không? Các giá trị đó là gì? Có lẽ bạn sẽ tốt hơn với một phương pháp gọi là IsSpecialCustomerLocation hoặc một cái gì đó thể hiện ý định thực sự của mã.

+0

cảm ơn. Nó khá chung chung. Tôi đã chỉ so sánh một giá trị enum - nó có liên quan đến lập trình GUI nên nó không có bất kỳ ý nghĩa kinh doanh nào như vậy. –

1

Bạn cũng có thể sử dụng phương pháp cú pháp LINQ cho nhiệm vụ đó (bằng cách sử dụng System.Linq namespace):

  object[] objects = new object[10]; 
     objects.Contains(new MyClass()); 

Hmm cho tôi nghĩ rằng một khoảnh khắc ... Oh bạn đã sử dụng nó. Nhưng bạn đã đặt nó vào một phương pháp riêng biệt thay vì gọi nó trực tiếp.

+0

Đó là quá nhiều việc phải làm mỗi lần. –

+0

cú pháp khởi tạo mảng sẽ thậm chí còn sạch hơn ... xem bài đăng của tôi. –

+0

Bạn nói đúng. Đồng ý! – Alexander

5

Nó là bất thường để viết một phương pháp mở rộng cho một hạn chế T. Không kém phần quan trọng, cách tiếp cận này sẽ nhanh chóng làm cho nội tâm của bạn trở nên khá khó sử dụng.

Trong khi hợp lệ, tôi có thể tránh phương thức này làm phương thức mở rộng - có lẽ chỉ cần sử dụng phương pháp tiện ích tĩnh chuẩn.

Cú pháp khởi tạo mảng C# 3 có thể dễ dàng hơn?

bool isTrue = new[] { 1, 2, 3 }.Contains(3); 

Tất nhiên, đối với bộ dữ liệu lớn, bạn có thể muốn một bộ nhớ cache HashSet<T> đâu đó ;-p

+0

cảm ơn cho bình luận Marc. bạn có thể giải thích tại sao điều này sẽ làm cho việc sử dụng intelliSense trở nên khó khăn? –

+0

Vì nó sẽ xuất hiện trên mọi biến duy nhất khi bạn nhấn ".". Nó chỉ mất một số phương pháp như vậy để bắt đầu làm cho nó khó khăn để tìm các phương pháp liên quan đến một loại ... trong thực tế, bạn sẽ không muốn sử dụng phương pháp này ** mà ** thường (tôi hy vọng) so với mọi phương pháp khác có sẵn. –

+0

Tôi thấy - điểm tốt. cảm ơn. –

1

Tôi sẽ làm cho một lớp tĩnh cho mục đích đó.Tôi không thích giải pháp đó bởi vì nó thêm một phương thức cho tất cả các lớp có vẻ hơi quá mức. Tuy nhiên nó theo một cách đi với OOD bởi vì bạn yêu cầu các đối tượng để thực hiện các chức năng trên chính mình (kinda).

Tuy nhiên, tôi sẽ đi với một lớp có thể tái sử dụng thay vì bởi vì tôi có thể thấy cách thức một antipattern có thể hình thành. Tôi không gọi nó là một antipattern được nêu ra, nhưng nếu quá nhiều của những xây dựng bật lên tôi sẽ gọi đó là một antipattern của dễ đọc kể từ khi mọi đối tượng sẽ nhận được lộn xộn với các phương pháp mở rộng. Tôi kinda nhìn nó như ô nhiễm không gian tên, nhưng ô nhiễm thành viên lớp học.

if (ConditionHelper.IsEqualToAny(value, value1, value2, value3)) 
{ 
    // Do something 
} 

Có cùng một công việc và không gây ô nhiễm bất cứ điều gì.

+0

Nghĩ về nó, nó bị một vấn đề dễ đọc.Nó phải làm với điều đó là không rõ ràng rằng giá trị được kiểm tra đối với value1, value2, value3 và vv. value.IsEqualToAny (value1, value2, value3) có khả năng đọc tốt hơn. Mối quan tâm của tôi chỉ là về các thành viên gây ô nhiễm. – Statement

1

Bạn có dự định thực hiện Chứa và đảm bảo bạn sẽ đăng ký Có trên tất cả các đối tượng có thể nơi bạn có thể sử dụng phương pháp mở rộng này không?

Nếu một số đối tượng nhất định kiểm tra bình đẳng bằng toán tử quá tải == thì giải pháp chung của bạn sẽ không thành công. Điều đó làm cho nó không phải là một sự tương đương thực sự của nhiều thử nghiệm ==. Đây cũng là một ví dụ điển hình về nguy cơ viết các phương pháp mở rộng!

Mã LINQ sau hoạt động khi bạn thực hiện quá tải toán tử cũng như nếu bạn đang sử dụng giá trị mặc định == của tham chiếu đối tượng, để nói rằng giá trị thực sự là cùng một đối tượng như value1, 2, 3 hoặc 4, V như các loại đối tượng của giá trị của bạn trong trường hợp đặc biệt này:

V[] lv = { value, value2, value3, value4 }; 
if (lv.Any(v => v==value)) 
    // do something 

Hoặc một phiên bản ngắn tay:

if (new List<V>{value, value2, value3, value4 }.Any(v => v==value)) 
    // do something 

tôi không thể có được các biểu thức lambda trên để làm việc trong một phương pháp khuyến nông chung .

Là một tốt (nếu không liên quan) ví dụ về những gì tôi nghĩ là một đáng yêu, cú pháp có thể đọc được, thành ngữ trong Python sẽ

if value in (value1, value2, value3, value4): 
+0

Tôi không thấy đây là vấn đề. Phương thức Contains (là một ExtensionMethod (được thực thi trong System.Linq.Enumerable)) sử dụng EqualityComparer (trong trường hợp mặc định) sử dụng một so sánh ==. –

+0

Có lẽ tôi đã thực hiện sai hoặc có điều gì đó về cách nó bị ràng buộc nhưng khi tôi kiểm tra nó, phương thức mở rộng không phát hiện được đối tượng là đối tượng khác nhưng bằng nhau dựa trên toán tử == overloading của nó. –

0

Nếu bạn chỉ kiểm tra một giá trị Enum (như bạn nói trong bình luận về Rogers trả lời), bạn nên sử dụng một FlagsAttribute trên Enum.

[Flags] 
public enum Value 
{ 
    Value1 = 0, 
    Value2 = 1, 
    Value3 = 2, 
    Value4 = 4 
} 

Value value = Value.Value1; 
if (value | Value.Value1 | Value.Value2 | Value.Value3 | Value.Value4) 
{ 
    // You can also use other bitwise operations, like & (AND),^(XOR) and ~ (NOT) 
} 

Nếu không; nếu nó là tên miền cụ thể, hãy thêm nó vào logic nghiệp vụ của bạn. Nếu nó là chung chung, hãy tạo một lớp trợ giúp.

+0

Tôi không nghĩ điều đó sẽ phù hợp. Chỉ vì tôi muốn kiểm tra một số giá trị khác nhau không có nghĩa là enum phải là một trường bit. Tôi không muốn giá trị enum là một giá trị kết hợp. - cảm ơn cho đầu vào của bạn mặc dù. Tôi đã sử dụng phương pháp mở rộng này trong một thời gian và nó đã khá hữu ích trong một số tình huống. –

Các vấn đề liên quan