2011-02-08 37 views
15

Tôi đang làm việc với một công việc cụ thể .NET plattform, được biên dịch trước chứ không phải OpenSource. Đối với một số tác vụ tôi cần phải mở rộng lớp này, nhưng không cần phải thừa kế từ nó. Tôi chỉ muốn thêm một phương thức.Làm cách nào để viết một phương thức mở rộng cho một kiểu chung với các ràng buộc về các tham số kiểu?

Lúc đầu, tôi muốn cho bạn thấy một dummycode lớp hiện có:

public class Matrix<T> where T : new() { 
    ... 
    public T values[,]; 
    ... 
} 

tôi muốn mở rộng lớp này theo cách sau:

public static class MatrixExtension { 
    public static T getCalcResult<T>(this Matrix<T> mat) { 
     T result = 0; 
     ... 
     return result; 
    } 
} 

Tôi đã có cú pháp này từ nhiều google liên kết để không biết liệu nó có đúng không. Trình biên dịch nói với tôi không có lỗi, nhưng cuối cùng nó không hoạt động. Cuối cùng, tôi muốn gọi hàm này theo cách sau:

Matrix<int> m = new Matrix<int>(); 
... 
int aNumber = m.getCalcResult(); 

Vì vậy, bất kỳ ai có ý tưởng? Cảm ơn sự giúp đỡ của bạn!

Trân Nem

+0

Tại sao bạn nghĩ nó không hoạt động? Nó có ném một ngoại lệ không? –

+1

Đây là cách thích hợp để sử dụng một phương pháp mở rộng, nhưng thay vì 'T result = 0' bạn nên có' T result = default (T) 'vì T ban đầu không bị ràng buộc với' int'.Ngoài ra, bạn nên kiểm tra để chắc chắn rằng bạn có câu lệnh sử dụng để bao gồm lớp MatrixExtension của bạn. Bạn luôn có thể kiểm tra bằng cách gọi trực tiếp 'MatrixExtension.getCalcResult (m)' để xem nó có hoạt động hay không. –

+0

Ít nhất IDE bắt buộc tôi gọi phương thức như sau: m.getCalcResult (); Nhưng khi tôi cố gắng biên dịch, tôi gặp lỗi khác: > 'Ma trận ' không chứa định nghĩa cho 'GetValue' và không có phương pháp mở rộng 'GetValue' chấp nhận đối số đầu tiên của loại 'Matrix ' tìm thấy (bạn đang thiếu một chỉ thị bằng cách sử dụng hoặc một tham chiếu lắp ráp?) Bằng cách này, cách gọi phương thức không có ý nghĩa vì thông số T chung đã được gán. –

Trả lời

23

Bạn cần thêm các ràng buộc thông số loại tương tự trên phương thức tiện ích mở rộng.

Đây là nỗ lực của tôi lúc xây dựng lại gần nhất của các ví dụ của bạn mà biên dịch và chạy, mà không cần bất kỳ lỗi:

public class Matrix<T> where T : new() { 
    public T[,] values; 
} 


public static class MatrixExtension { 
    public static T getCalcResult<T>(this Matrix<T> mat) where T : new() { 
     T result = new T(); 
     return result; 
    } 
} 

class Program { 
    static void Main(string[] args) { 
     Matrix<int> m = new Matrix<int>(); 
     int aNumber = m.getCalcResult(); 
     Console.WriteLine(aNumber); //outputs "0" 
} 
+0

Tôi đã suy ngẫm về việc đăng mã của tôi, nhưng nó giống hệt nhau. – Marlon

+0

Bạn có thể sao chép/dán mã _my_ vào một dự án mới để xem điều gì xảy ra. –

+0

Đúng, nó hoạt động! Nhưng bây giờ tôi biết những gì tôi đã không nhìn! 'lớp Ma trận trong đó T: new()' Tôi hoàn toàn không xem xét điều đó. :( –

-2

Các bạn đã nhìn vào "trang trí" ...

Sample showing Decorator patterns

Một trang trí cho phép bạn tạo ra một lớp với các thuộc tính và phương pháp riêng của mình mà không làm một nguồn gốc trực tiếp từ một lớp cụ thể. Sau đó, bạn có thể "áp dụng" nó cho hầu như bất kỳ đối tượng nào khác. Sau đó, bạn có thể áp dụng các phương pháp bổ sung hoặc các thuộc tính mà bạn đang cố gắng làm việc.

Mẫu này là một khám phá nhanh chóng đơn giản cho thấy một ví dụ như vậy gắn bản thân để "xe hơi" bằng cách xây dựng "lựa chọn" ...

+1

Đó không thực sự là câu trả lời cho câu hỏi của anh ấy. –

+0

@Jim Schubert, vâng ... Tôi biết ... trong khi tôi đang cố tra cứu một số mẫu, bàn di chuột phải bị trúng ... cho đến khi tôi quay lại để điều chỉnh ... – DRapp

+0

Tôi đã không xuống bỏ phiếu, nhưng tôi muốn nói ... những lần tiếp xúc trên bàn di chuột này mang lại cho tôi mọi thời gian. Ngoài ra, +1 bởi vì một người trang trí có thể giải quyết vấn đề và là một câu trả lời khả thi. Bình luận đầu tiên của tôi thực sự hướng đến câu hỏi một câu phù hợp hơn với một câu trả lời như thế nào: \ –

2

Ngay bây giờ, các "lỗi" duy nhất tôi muốn thấy là thế này:

T result = 0; 

Bạn có thể thay đổi điều đó để:

T result = default(T); 

trong trường hợp của các loại giá trị, đây sẽ là zero, vì vậy nó sẽ được an toàn.

Tuy nhiên, bạn sẽ thấy rằng điều này là khó khăn khi bạn đến phần "..." mà bạn đã liệt kê. Các loại cơ bản (int, double, v.v.) không triển khai phương pháp bạn có thể sử dụng để tính toán toán học của mình. Đây là long time, very highly voted request on Connect, btw.

Trong khi có giải pháp thay thế, chúng khiến cuộc sống trở nên rất khó khăn. Không giống như các mẫu trong C++, các generics của C# thực sự không hỗ trợ các phép toán an toàn kiểu trên các kiểu tùy ý.

+0

Tôi nghĩ rằng đây là vấn đề của tôi mà sẽ vẫn còn. Nhưng đó không phải là câu hỏi của tôi. Câu hỏi của tôi là làm thế nào để mở rộng lớp chung này. Đối với một lớp học ungener thì không có vấn đề gì. –

+0

@ nemcija: Có - nhưng việc mở rộng lớp học chung là chính xác như bạn đã làm - đó không phải là vấn đề. Đây là những gì bạn sẽ chạy vào khi bạn nhận được lỗi biên dịch cố định. –

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