2008-09-22 24 views
18

Trong Java, người ta có thể khai báo một biến parameterised bởi một "không rõ" kiểu chung chung, mà trông như thế này:Có thẻ chung "ẩn danh" trong C#, như '?' trong Java?

Foo<?> x; 

Có một cấu trúc tương đương với này dấu hỏi, trong C#?

+0

Loại mẫu cuối cùng được giải quyết là gì? –

Trả lời

26

Câu trả lời ngắn gọn là không. Không có một tính năng tương đương trong C#.

Một cách giải quyết, từ C# from a Java developer's perspective bởi Dare Obasanjo:

Trong một số trường hợp, người ta có thể cần phải tạo ra một phương pháp mà có thể hoạt động trên cấu trúc dữ liệu chứa bất kỳ loại như trái ngược với những người mà chứa một loại cụ thể (ví dụ như một phương pháp để in tất cả các đối tượng trong một cấu trúc dữ liệu) trong khi vẫn tận dụng lợi thế của việc gõ mạnh vào generics. Cơ chế để xác định điều này trong C# là thông qua một tính năng được gọi là kiểu chung trong khi hội nghị trong Java được thực hiện bằng cách sử dụng các loại ký tự đại diện. Các mẫu mã sau đây cho thấy cách cả hai cách tiếp cận dẫn đến cùng một kết quả.

C# Mã

using System; 
using System.Collections; 
using System.Collections.Generic; 

class Test{ 

    //Prints the contents of any generic Stack by 
    //using generic type inference 
    public static void PrintStackContents<T>(Stack<T> s){ 
     while(s.Count != 0){ 
      Console.WriteLine(s.Pop()); 
     } 
    } 

    public static void Main(String[] args){ 

    Stack<int> s2 = new Stack<int>(); 
    s2.Push(4); 
    s2.Push(5); 
    s2.Push(6); 

    PrintStackContents(s2);  

    Stack<string> s1 = new Stack<string>(); 
    s1.Push("One"); 
    s1.Push("Two"); 
    s1.Push("Three"); 

    PrintStackContents(s1); 
    } 
} 

Java Mã

import java.util.*; 

class Test{ 

    //Prints the contents of any generic Stack by 
    //specifying wildcard type 
    public static void PrintStackContents(Stack<?> s){ 
     while(!s.empty()){ 
      System.out.println(s.pop()); 
     } 
    } 

    public static void main(String[] args){ 

    Stack <Integer> s2 = new Stack <Integer>(); 
    s2.push(4); 
    s2.push(5); 
    s2.push(6); 

    PrintStackContents(s2);  

    Stack<String> s1 = new Stack<String>(); 
    s1.push("One"); 
    s1.push("Two"); 
    s1.push("Three"); 

    PrintStackContents(s1); 
    } 
} 
+1

C# -like suy luận hoạt động cũng trong Java 6. Vẫn còn sử dụng trong Java sau đó? –

+21

Điều này không thực sự trả lời câu hỏi. Câu trả lời là không". Bí quyết được trình bày ở trên minh họa một cách giải quyết cho việc chuyển đổi bắt giữ của Java trong C# hoạt động với chuyển đổi lời gọi phương thức, nhưng sẽ không hữu ích trong chuyển đổi chuyển nhượng hoặc trong một biểu thức truyền. – Mishax

+4

Trong thực tế, câu trả lời này là cách dài nhất để nói "không" tôi từng thấy :) – David

1

Không, thực sự không có khái niệm tương tự trong C#. Bạn sẽ cần phải tham khảo một lớp cơ sở của Foo (có thể là không chung chung Foo), hoặc làm cho phương pháp bạn đang làm việc trong chính nó (để bạn có thể tham khảo Foo, và để cho người gọi phương pháp của bạn xác định những gì T Là).

Hy vọng điều đó sẽ hữu ích.

4

Không có cú pháp tương đương trong C#.

12

AFAIK bạn không thể làm điều đó trong C#. BCL làm gì và có rất nhiều ví dụ để tạo ra một lớp không phải là chung chung và sau đó tạo một lớp chung mà thừa hưởng hành vi cơ sở từ hành vi trước đó. Xem ví dụ bên dưới.

class Foo 
{ 
} 

class Foo<T> : Foo 
{ 
} 

Các bạn có thể viết một cái gì đó như thế này:

Foo t = new Foo<int>(); 
3

Nó không phải là (khá) đúng là không có tương đương trong C#. Không có tương đương tĩnh mà bạn có thể sử dụng làm kiểu hoặc gọi phương thức, đủ chính xác. Để làm điều đó, hãy sử dụng Jorge's answer.

Mặt khác, đôi khi bạn cần ý tưởng tương đương để phản chiếu và có tương đương với ý tưởng đó. Nếu bạn có:

interface IFoo<T> 
{ 
    T Bar(T t, int n); 
} 

bạn có thể có được một Type đại diện IFoo<int> sử dụng typeof(IFoo<int>). Ít nổi tiếng hơn, và câu trả lời một phần cho câu hỏi của bạn, là bạn cũng có thể nhận được một số Type đại diện cho IFoo<T> sử dụng typeof(IFoo<>).

Điều này hữu ích khi bạn muốn sử dụng IFoo<T> cho một số T thông qua phản ánh và sẽ không biết T cho đến khi thời gian chạy.

Type theInterface = typeof(IFoo<>); 
Type theSpecificInterface = theInterface.MakeGenericType(typeof(string)); 

// theSpecificInterface now holds IFoo<string> even though we may not have known we wanted to use string until runtime 

// proceed with reflection as normal, make late bound calls/constructions, emit DynamicMethod code, etc. 
11

Mặc dù được thừa nhận không phải là cách tiếp cận rõ ràng, sử dụng Foo<object> x cũng có thể phù hợp.

+2

-1: sử dụng 'đối tượng' hạn chế loại chung cho tất cả các loại có siêu lớp' đối tượng' chung. –

+3

Làm việc với mọi thứ: nguyên thủy, đối tượng lớp, cấu trúc, enums ... 'Danh sách list = new List (); list.Add (1); list.Add (new DateTime()); list.Add (new MyStruct()); list.Add (MyEnum.Enum1); ' – Dani

+0

Tôi thừa nhận bạn đúng. –

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