2009-08-07 40 views
26

Có một cách đơn giản để thực hiện điều này, và nếu có thể mà không instanciating một đối tượng:C# giao diện phương pháp tĩnh gọi với Generics

interface I 
{ 
    static string GetClassName(); 
} 

public class Helper 
{ 

    static void PrintClassName<T>() where T : I 
    { 
     Console.WriteLine(T.GetClassName()); 
    } 
} 
+0

Cách triển khai giao diện của bạn sẽ như thế nào? – dtb

+2

Cho rằng các giao diện xác định các thành viên cá thể, làm thế nào để bạn mong đợi để gọi một thành viên giao diện mà không có một cá thể? nếu bạn muốn tên lớp, sử dụng typeof (T) và đổ giao diện. – meandmycode

+0

Bạn đang cố gắng đạt được điều gì ở đây? Chắc chắn 'typeof (T) .FullName' sẽ thực hiện công việc? –

Trả lời

24

Hãy thử một phương pháp mở rộng thay vì:

public interface IMyInterface 
{ 
    string GetClassName(); 
} 

public static class IMyInterfaceExtensions 
{ 
    public static void PrintClassName<T>(this T input) 
     where T : IMyInterface 
    { 
     Console.WriteLine(input.GetClassName()); 
    } 
} 

Điều này cho phép bạn thêm các phương pháp khuyến nông/tiện ích tĩnh, nhưng bạn vẫn cần một thể hiện của thực hiện IMyInterface của bạn.

Bạn không thể có giao diện cho các phương pháp tĩnh vì nó sẽ không có ý nghĩa, chúng là các phương thức tiện ích không có cá thể và do đó chúng không thực sự có kiểu.

+0

Ok, nhưng bạn có nghĩ rằng chúng ta có thể tránh tham số đầu vào. Giả sử chúng ta có một kiểu mẫu đơn cho giao diện hoặc theo bất kỳ cách nào khác? – Toto

+1

Lưu ý chắc chắn ý bạn là gì - bạn sẽ gọi phương thức mở rộng này như thể nó là một ví dụ: new MyImplementation(). PrintClassName() – Keith

+2

Bạn không thể tránh trường hợp này, trừ khi bạn chuyển sang sử dụng sự phản chiếu (như @Kent Boogaart's câu trả lời), nhưng sau đó bạn không nên thực sự sử dụng generics như bạn chỉ cần đi qua các loại – Keith

3

Tôi cũng đã cố gắng để thiết lập một phương pháp tĩnh trên một giao diện một chút thời gian trước, không chắc chắn tại sao bây giờ. Tôi đã đánh dấu này như vậy có lẽ nó giúp:

Interface with a static method by using extension methods

7

Bạn không thể kế thừa phương pháp tĩnh. Mã của bạn sẽ không biên dịch theo bất kỳ cách nào, bởi vì một giao diện không thể có các phương thức tĩnh vì điều này.

Theo trích dẫn từ littleguru:

Thừa kế trong .NET chỉ hoạt động trên cơ sở dụ. Phương thức tĩnh là được xác định ở cấp loại không nằm ở cấp độ cá thể . Đó là lý do tại sao ghi đè không hoạt động với static phương pháp/thuộc tính/sự kiện ...

Phương pháp tĩnh chỉ được tổ chức một lần trong bộ nhớ . Không có bảng ảo, v.v. được tạo cho chúng.

Nếu bạn gọi phương thức thể hiện trong .NET, bạn luôn cung cấp phiên bản hiện tại . Điều này bị ẩn bởi thời gian chạy .NET , nhưng điều đó xảy ra. Mỗi phương thức có tham số đầu tiên là một con trỏ (tham chiếu) đến đối tượng mà phương thức được chạy. Điều này không xảy ra với phương pháp tĩnh (vì chúng là được xác định ở cấp loại). Làm thế nào nên trình biên dịch quyết định chọn phương thức để gọi?

+1

Để chắc chắn trình biên dịch không thể chọn (hoặc nếu anh ta có thể điều đó bởi vì chúng tôi rõ ràng gọi focntion tĩnh phải với lớp bên phải). Tuy nhiên chúng ta có thể không có cái gì đó xung quanh điều này với genereic? – Toto

+0

Có lẽ nó có thể là có thể. Nhưng thiết kế này được chọn để giữ cho nó đơn giản và sạch sẽ hơn. – Dykam

3

Nếu bạn chỉ sau tên loại, bạn chỉ có thể làm điều này:

public class Helper 
{ 
    static void PrintClassName<T>() 
    { 
     Console.WriteLine(typeof(T).Name); 
    } 
} 
+0

Câu trả lời hay (+1) nhưng tôi muốn thêm rằng bạn không nên thực sự làm điều này - nếu tất cả những gì bạn đang làm là chuyển một loại, bạn nên sử dụng thông số thay thế: PrintClassName (Kiểu nhập) {Console.WriteLine (đầu vào .Tên); } – Keith

1

Câu trả lời là một trình độ "không thực sự nhưng loại". Bạn có thể cung cấp một phương thức mở rộng tĩnh cho tất cả các trình triển khai của một giao diện cụ thể và sau đó có thể gọi phương thức này từ trình triển khai của bạn trong thuộc tính hoặc phương thức khác. Như một ví dụ:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace InterfacesWithGenerics 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Helper.PrintClassName<Example>(new Example()); 
      Console.ReadLine(); 
     } 
    } 

    public class Example : I 
    { 
     #region I Members 

     public string ClassName 
     { 
      get { return this.GetClassName(); } 
     } 

     #endregion 
    } 

    public interface I 
    { 
     string ClassName { get; } 
    } 

    public class Helper 
    { 

     public static void PrintClassName<T>(T input) where T : I 
     {   
      Console.WriteLine(input.GetClassName()) ; 
     } 
    } 

    public static class IExtensions 
    { 
     public static string GetClassName(this I yourInterface) 
     { 
      return yourInterface.GetType().ToString(); 
     } 
    } 
} 

Ở đây chúng ta có một giao diện (I) trong đó xác định các bất động sản chúng tôi quan tâm và một phương pháp khuyến nông tĩnh (GetClassName) được áp dụng cho tất cả các thành viên của loại hình của nó mà hiện các công việc khó khăn nhận được thông tin chúng tôi muốn. Chúng ta có một lớp (ví dụ) thực hiện giao diện I, vì vậy khi chúng ta gọi lớp trợ giúp tĩnh của chúng ta đi qua trong một cá thể của ví dụ, nó chạy phương thức tĩnh chống lại nó.Thật không may là không hợp lệ để tham chiếu kiểu T trực tiếp trong chính phương thức đó như một biến, bạn sẽ phải chuyển một cá thể vào ứng dụng.

2

Khai báo staticproperty, event hoặc method trên định nghĩa giao diện không được coi là định nghĩa hợp pháp. Điều này là do giao diện được coi là hợp đồng và như vậy, đại diện cho một cái gì đó mà sẽ được thực hiện bởi mỗi cá thể khách hàng của giao diện đó.

Tuyên bố static về cơ bản cho biết thành viên static không yêu cầu triển khai thực thể khách hàng để thực thi chức năng bắt buộc và điều này thiếu khái niệm chung về giao diện:

0

Bạn có thể xác định className là thuộc tính trên lớp cụ thể. Đây là ay ưa thích để lưu trữ siêu dữ liệu trong .net. Bằng cách này bạn có thể truy vấn thuộc tính cho lớp đã cho và bạn không cần một cá thể.

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