2012-01-04 24 views
36

Theo tiêu đề, có thể khai báo ràng buộc loại bỏ trong C# 4 không?generic KHÔNG ràng buộc ở đâu T:! IEnumerable

+6

thậm chí nếu có, bạn có thể mô tả một trường hợp sử dụng? –

+1

Thật lạ khi quan sát bạn có một yêu cầu như vậy. bạn chỉ có thể viết mã với loại T mà bạn biết rằng thuộc về một họ lớp. Làm thế nào bạn có thể mã trong generics nếu không? Hoặc bạn không cần generics trong trường hợp này hoặc bạn cần phải sửa đổi trường hợp sử dụng của bạn. –

+2

trường hợp sử dụng được quan tâm là cho phép các quá tải sau cùng tồn tại 'void doIt (T gì) {}' 'void doIt (IEnumerable whats) {}' - tại thời điểm có sự mơ hồ vì 'T 'trong phương thức đầu tiên có thể là một' IEnumerable <> '(vì vậy tôi muốn xác định rằng' T' KHÔNG nên là 'IEnumerable') ... – Cel

Trả lời

36

Không - không có khái niệm nào như vậy trong C# hoặc trong CLR.

+0

Khái niệm này sẽ biến nó thành C# và/hoặc CLR trong tương lai? –

+0

@RandRandom: Tôi chưa từng nghe về bất kỳ kế hoạch nào cho nó. –

0

Không, nhưng nó sẽ có thể kiểm tra với một "là" và sau đó xử lý nó một cách thích hợp ...

1

Bạn sử dụng một hạn chế, do đó bạn có thể đảm bảo các loại mà bạn sử dụng có một số thuộc tính/phương pháp/.. . bạn muốn sử dụng.

Một chung chung với một ràng buộc loại-phủ định không có ý nghĩa gì, vì không có mục đích để biết sự vắng mặt của một số thuộc tính/phương pháp bạn không muốn sử dụng.

+0

rõ ràng là bạn chưa nhận được lỗi: ## '' không thể triển khai cả '>' và '>' vì chúng có thể hợp nhất cho một số thay thế tham số kiểu ##. Chắc chắn có trường hợp khi bạn muốn xác định rằng genericstype2 không thể là generictype4 –

+0

Tôi đã có thể làm việc xung quanh kịch bản của mình bằng cách sử dụng một loạt các lớp trừu tượng thực hiện một thể hiện của giao diện tương tự và kế thừa lớp trừu tượng. đó là cách Action và cứ như vậy .. –

4

Theo như tôi biết thì không thể thực hiện điều đó.

gì bạn có thể làm một số kiểm tra thời gian chạy:

public bool MyGenericMethod<T>() 
{ 
    // if (T is IEnumerable) // don't do this 

    if (typeof(T).GetInterface("IEnumerable") == null) 
     return false; 

    // ... 

    return true; 
} 
+1

Bạn không thể sử dụng 'is' như thế - nó kiểm tra xem một đối tượng * có tương thích với một loại hay không. –

+2

ý của bạn là 'if (typeof (T) == typeof (IEnumerable)) {}' – kev

0

một sử dụng cho điều này sẽ là một loại tùy chọn.

public class Option<A,B> 
where A : !B 
where B : !A 
{ 
    private readonly A a; 
    private readonly B b; 

    private Option(){} 

    public Option(A a) 
    { 
     this.a = a 
    } 

    public Option(B b) 
    { 
     this.b = b 
    } 
} 

Kiểm tra thời gian chạy sẽ hoạt động nhưng bạn sẽ không có lợi ích khi kiểm tra loại lúc biên dịch.

2

tôi thấy bản thân tôi cố gắng để thực hiện các cùng trường hợp đề cập trong các ý kiến:

void doIt<T>(IEnumerable<T> what) { } 
void doIt<T>(T whats) { } 

tôi trừ đoạn mã sau để tham khảo các phương pháp đầu tiên:

doIt(new List<T>()); 

Nhưng nó thực sự tham chiếu đến giây thứ hai.

Một giải pháp là cast lập luận như thế này:

doIt(new List<T>().AsEnumerable<T>()); 

Dàn diễn viên có thể được ẩn bởi tình trạng quá tải khác:

void doIt<T>(List<T> whats) { 
    doIt(whats.AsEnumerable<T>()); 
} 
Các vấn đề liên quan