2010-08-30 31 views
7

thể trùng lặp:
Solution for overloaded operator constraint in .NET genericsXác định một generic mà thực hiện các nhà điều hành +

Tôi có một vấn đề tôi đang làm việc trên, hiện nay nó đang làm việc cho int s nhưng tôi muốn nó để làm việc cho tất cả các lớp có thể được thêm bằng toán tử +. Có cách nào để xác định điều này trong chung chung? Ví dụ:

public List<T> Foo<T>() where T : ISummable 

Có cách nào để thực hiện việc này không?

EDIT:
Hiệu suất truyền trong đại biểu để thực hiện tổng hợp thay vì sử dụng + = với loại Int chậm nhất là 540%. Điều tra giải pháp có thể khác

Giải pháp cuối cùng:
Cảm ơn tất cả các đề xuất của bạn. Tôi đã kết thúc với một giải pháp mà không phải là quá chậm và thực thi việc kiểm tra tại thời gian biên dịch. Tôi không thể lấy hết tín dụng như một đồng nghiệp đã giúp tôi đạt được điều này. Dù sao, ở đây là:

Thực hiện một giao diện với tất cả các nhà khai thác cần thiết trên đó theo hình thức chức năng

public interface IFoo<InputType, OutputType> 
{ 
    //Adds A to B and returns a value of type OutputType 
    OutputType Add(InputType a, InputType b); 
    //Subtracts A from B and returns a value of type OutputType 
    OutputType Subtract(InputType a, InputType b); 
} 

Tạo lớp bạn muốn xác định, nhưng thay vì mệnh đề ở đâu, sử dụng một sự phụ thuộc được tiêm vào trong giao diện IFoo. OutputType thường sẽ tăng gấp đôi vì bản chất của các phép toán là toán học.

public class Bar<T> 
{ 
    private readonly IFoo<T,double> _operators; 

    public Bar(IFoo<T, double> operators) 
    { 
     _operators = operators; 
    } 
} 

bây giờ khi bạn sử dụng lớp này, bạn xác định các quy tắc cho hoạt động như thế này:

private class Foo : IFoo<int, double> 
{ 
    public double Add(int a, int b) 
    { 
     return (double)(a+b); 
    } 
    public double Subtract(int a, int b) 
    { 
     return (double)(a-b); 
    } 
} 

sau đó bạn sẽ sử dụng nó như thế này:

Foo inttoDoubleOperations = new Foo(); 
Bar myClass = new Bar(Foo); 

như vậy tất cả các hoạt động được thực thi tại thời gian biên dịch :)

tận hưởng!

+1

Không, không trực tiếp. Có một bài viết trên CodeProject tuy nhiên mô phỏng này. – leppie

+0

Cảm ơn bạn đã trả lời. Bạn có thể gửi cho tôi một liên kết đến giải pháp không? – TerrorAustralis

+0

Tại sao không có phương pháp trong ISummable có thể thêm hai T chẳng hạn như T Thêm (T đầu tiên, T giây)? Sử dụng toán tử + để bổ sung IMO sẽ liên quan đến sự phản chiếu gọi phương thức op_Addition. – VinayC

Trả lời

8

Đây là một tính năng mới được yêu cầu khá phổ biến đối với C#: khả năng chỉ định nhiều ràng buộc thông số chung hơn so với những điều chúng tôi đã có. Các nhà khai thác là một trong những người được hỏi nhiều nhất. Tuy nhiên, C# hiện không hỗ trợ điều này.

cách giải quyết có thể:

  • Vượt qua một đại biểu cho bất kỳ phương pháp mà cần phải làm thêm. Đây là tùy chọn an toàn nhất, nhưng tất nhiên sẽ rất khó chịu nếu bạn cần gọi phương thức này thường xuyên. Ví dụ:

    public class Generic<T> { 
        public void DoSomething(T anItem, T anotherItem, Func<T, T, T> add) { 
         // instead of 
         Blah(anItem + anotherItem); 
         // have to write: 
         Blah(add(anItem, anotherItem)); 
        } 
    } 
    
    Generic<int> genInt = ...; 
    // and then instead of ... 
    genInt.DoSomething(1, 2); 
    // have to write: 
    genInt.DoSomething(1, 2, (a, b) => a + b); 
    
  • Khai báo giao diện riêng của bạn IAddable. Sau đó, bạn có thể sử dụng nó làm ràng buộc thông số loại chung, nhưng rõ ràng là bạn không thể sử dụng int làm thông số sau đó. Bạn sẽ phải sử dụng một struct của riêng bạn mà chỉ chứa một int và mà thực hiện IAddable:

    public interface IAddable<T> { 
        T Add(T other); 
    } 
      
    public struct Integer : IAddable<Integer> { 
        public int Value; 
        public Integer(int value) { Value = value; } 
        public Integer Add(Integer other) { return new Integer(Value + other.Value); } 
    } 
    
    // then instead of 
    Generic<int> blah = ...; 
    // have to write: 
    Generic<Integer> blah = ...; 
    
  • dynamic. Một giải pháp khác có thể là sử dụng dynamic, nhưng điều này khá khó khăn và hoàn toàn không an toàn: nó sẽ cho phép bạn chuyển bất kỳ loại nào và gọi bất kỳ phương thức hoặc nhà điều hành nào và chỉ gặp sự cố khi chạy, không phải lúc biên dịch.

+0

Cảm ơn, tôi có thể kết thúc bằng cách chuyển tiếp phương thức đại biểu. Nó có vẻ như một cách giải quyết hợp lý và sẽ không thêm quá nhiều nỗ lực vào phần người dùng. Cảm ơn bạn! – TerrorAustralis

1

Trong C# 4.0 là từ khóa mới động cho phép bạn thực hiện việc này khi chạy. Trong các phiên bản trước nó có thể nhưng quá râm và khó cho tôi. Nhưng bạn có thể allways vượt qua một đại biểu sẽ thực hiện bổ sung bên trong chung chung. Nếu không, nó không thể vì không có ISummable, IAdditive và nói chung không có cách nào để biết là cái gì đó là phụ gia * tại thời gian biên dịch. Nếu bạn muốn một số ý kiến ​​thêm tôi sẽ thêm nó sau này. BR.

  • Ý tôi là, ngoại trừ việc bạn sở hữu IAdditive và đánh dấu một số loại với chúng, nhưng nó sẽ không hoạt động ví dụ với int.
+0

Cảm ơn bạn đã trả lời! Bạn nhấn móng tay ngay trên đầu với bình luận của bạn về IAdditive. Tôi không thể làm việc đó cho ints và các lớp/cấu trúc được triển khai trước khác – TerrorAustralis

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