2013-03-22 36 views
13

Hãy nói rằng tôi có một lớp chung như sau:Wildcard tương đương trong C# Generics

public class GeneralPropertyMap<T> 
{ 
} 

Trong một số lớp khác tôi có một phương pháp mà mất trong một loạt các GeneralPropertyMap<T>. Trong Java, để mất trong một mảng có chứa bất kỳ loại GeneralPropertyMap phương pháp này sẽ trông như thế này:

private void TakeGeneralPropertyMap(GeneralPropertyMap<?>[] maps) 
{ 
} 

Chúng tôi sử dụng các ký tự đại diện để sau này chúng ta có thể gọi TakeGeneralPropertyMap đi qua một loạt các GeneralPropertyMap với bất kỳ loại cho T mỗi loại, như sau:

GeneralPropertyMap<?>[] maps = new GeneralPropertyMap<?>[3]; 
maps[0] = new GeneralPropertyMap<String>(); 
maps[1] = new GeneralPropertyMap<Integer>(); 
maps[2] = new GeneralPropertyMap<Double>(); 
//And finally pass the array in. 
TakeGeneralPropertyMap(maps); 

Tôi đang cố gắng tìm ra điểm tương đương trong C# không thành công. Bất kỳ ý tưởng?

+0

Các bạn đã thử làm cho chức năng chụp 'GeneralPropertyMap [] maps' .. Tôi đoán nó phải làm việc vì Hiệp phương sai – Ankur

Trả lời

3

Không có tương đương trực tiếp với điều này trong C#.

Trong C#, điều này sẽ thường được thực hiện bằng việc có lớp generic của bạn thực hiện một giao diện hoặc cơ sở không chung lớp:

interface IPropertyMap 
{ 
    // Shared properties 
} 

public class GeneralPropertyMap<T> : IPropertyMap 
{ 
} 

Sau đó bạn có thể vượt qua một mảng của những:

IPropertyMap[] maps = new IPropertyMap[3]; 
// ... 

TakePropertyMap(maps); 
+0

@EricJ. Đã hiểu sai vấn đề ... cố định –

+0

Tôi hiểu các phương pháp chung, nhưng chúng sẽ không thực hiện trong trường hợp này.Mỗi khi tôi gọi nó, tôi chỉ có thể chỉ định một loại cho GeneralPropertyMap. Vì vậy, tôi chỉ có thể gọi nó đi qua một mảng của GeneralPropertyMap [] hoặc GeneralPropertyMap , v.v. – AxiomaticNexus

15

Generics trong C# đảm bảo mạnh mẽ hơn Generics trong Java. Vì vậy, để làm những gì bạn muốn trong C#, bạn phải để cho lớp GeneralPropertyMap<T> kế thừa từ một phiên bản không chung của lớp đó (hoặc giao diện).

public class GeneralPropertyMap<T> : GeneralPropertyMap 
{ 
} 

public class GeneralPropertyMap 
{ 
    // Only you can implement it: 
    internal GeneralPropertyMap() { } 
} 

Bây giờ bạn có thể làm:

private void TakeGeneralPropertyMap(GeneralPropertyMap[] maps) 
{ 
} 

Và:

GeneralPropertyMap[] maps = new GeneralPropertyMap[3]; 
maps[0] = new GeneralPropertyMap<String>(); 
maps[1] = new GeneralPropertyMap<Integer>(); 
maps[2] = new GeneralPropertyMap<Double>(); 
TakeGeneralPropertyMap(maps); 
+1

Nó vẫn chưa đủ tốt vì trong giao diện bạn sẽ muốn có một phương thức trả về hoặc lấy một ký tự đại diện để sử dụng từ phương thức "TakeGeneralPropertyMap" mà bạn không thể làm vì chúng ta không muốn giao diện của một loại chung. Tuy nhiên, câu trả lời này ít nhất là gần gũi. Cảm ơn :-) – AxiomaticNexus

0

Thực hiện một giao diện từ các thành viên của GeneralPropertyMap (IGeneralPropertyMap), và sau đó đi một IGeneralPropertyMap[] như một cuộc tranh cãi.

8

Trong khi, như những người khác đã lưu ý, không có sự tương ứng chính xác với ký tự đại diện trong C#, một số trường hợp sử dụng của chúng có thể được bao phủ bằng covariance/contravariance.

public interface IGeneralPropertyMap<out T> {} // a class can't be covariant, so 
             // we need to introduce an interface... 

public class GeneralPropertyMap<T> : IGeneralPropertyMap<T> {} // .. and have our class 
                  // inherit from it 

//now our method becomes something like 
private void TakeGeneralPropertyMap<T>(IList<IGeneralPropertyMap<T>> maps){} 

// and you can do 
    var maps = new List<IGeneralPropertyMap<Object>> { 
     new GeneralPropertyMap<String>(), 
     new GeneralPropertyMap<Regex>() 
    }; 
    //And finally pass the array in. 
    TakeGeneralPropertyMap<Object>(maps); 

Thông báo trước là bạn không thể sử dụng hiệp phương sai với kiểu giá trị, vì vậy thêm một GeneralPropertyMap<int>() mới vào danh sách của chúng tôi thất bại tại thời gian biên dịch.

cannot convert from 'GeneralPropertyMap<int>' to 'IGeneralPropertyMap<object>' 

Cách tiếp cận này có thể được thuận tiện hơn việc có một phiên bản không phải chung của lớp học của bạn/interfaces trong trường hợp bạn muốn hạn chế các loại mà GeneralPropertyMap có thể chứa. Trong trường hợp đó:

public interface IMyType {} 
public class A : IMyType {} 
public class B : IMyType {} 
public class C : IMyType {} 

public interface IGeneralPropertyMap<out T> where T : IMyType {} 

cho phép bạn có:

var maps = new List<IGeneralPropertyMap<IMyType>> { 
    new GeneralPropertyMap<A>(), 
    new GeneralPropertyMap<B>() , 
    new GeneralPropertyMap<C>() 
}; 
TakeGeneralPropertyMap(maps); 
Các vấn đề liên quan