2009-04-02 81 views
56

Làm cách nào để so sánh các loại đối tượng được khai báo dưới dạng loại.C# Loại đối tượng So sánh

Tôi muốn biết hai đối tượng có cùng loại hoặc từ cùng một lớp cơ sở hay không.

Mọi trợ giúp đều được đánh giá cao.

ví dụ:

private bool AreSame(Type a, Type b) { 

} 

Trả lời

84

Nói ab là hai đối tượng. Nếu bạn muốn xem nếu ab là trong hệ thống phân cấp thừa kế cùng, sau đó sử dụng Type.IsAssignableFrom:

var t = a.GetType(); 
var u = b.GetType(); 

if (t.IsAssignableFrom(u) || u.IsAssignableFrom(t)) { 
    // x.IsAssignableFrom(y) returns true if: 
    // (1) x and y are the same type 
    // (2) x and y are in the same inheritance hierarchy 
    // (3) y is implemented by x 
    // (4) y is a generic type parameter and one of its constraints is x 
} 

Nếu bạn muốn kiểm tra nếu có một lớp cơ sở của người kia, sau đó thử Type.IsSubclassOf.

Nếu bạn biết lớp cơ sở cụ thể, sau đó chỉ cần sử dụng is keyword:

if (a is T && b is T) { 
    // Objects are both of type T. 
} 

Nếu không, bạn sẽ phải đi bộ hệ thống phân cấp thừa kế trực tiếp.

+0

+1 Tôi đã không nhận thức được rằng chức năng tiện dụng IsAssignableFrom, tôi sẽ phải ghi nhớ điều đó. – James

+0

Có khá nhiều công cụ hữu ích trong hệ thống phân cấp Phản ánh! Thật thú vị khi duyệt qua danh sách thành viên - rất có thể bạn sẽ tìm thấy những gì mình cần. Do đọc tài liệu, mặc dù. Ví dụ, IsAssignableFrom sẽ trả về true nếu t là một tham số kiểu generic và u là một ràng buộc. –

+0

Chỉ cần FYI, tuy nhiên, điều này sẽ không trở lại đúng nếu hai lớp có cùng một lớp cơ sở. –

13

Bạn cũng có thể sử dụng từ khóa "IS" nếu bạn mong đợi hai trường hợp đối tượng thuộc một loại nhất định. Điều này cũng sẽ làm việc để so sánh các lớp con với các lớp cha và cũng là các lớp thực hiện các giao diện và vv. Điều này sẽ không hoạt động đối với các loại kiểu mặc dù.

if (objA Is string && objB Is string) 
// they are the same. 

public class a {} 

public class b : a {} 

b objb = new b(); 

if (objb Is a) 
// they are of the same via inheritance 
+0

Tôi không biết họ có thể là loại nào, chỉ cần biết liệu chúng có giống nhau hoặc từ cùng một lớp cơ sở hay không. –

+1

Điều này chỉ hoạt động trên các trường hợp loại, không phải cho các loại loại. –

31

Có một chút vấn đề với ý tưởng này, tuy nhiên, vì mọi đối tượng (và, thực sự, mọi loại) đều có một lớp cơ sở chung là Object. Những gì bạn cần xác định là cách xa chuỗi chuỗi thừa kế bạn muốn đi (cho dù đó là chúng giống nhau hoặc chúng có cùng cha mẹ trực tiếp hoặc một là cha mẹ trực tiếp của người khác, v.v.) và thực hiện kiểm tra theo cách đó. IsAssignableFrom rất hữu ích để xác định xem các loại có tương thích với nhau hay không, nhưng sẽ không hoàn toàn thiết lập nếu chúng có cùng cha/mẹ (nếu đó là những gì bạn đang theo dõi).

Nếu tiêu chuẩn khắt khe của bạn là chức năng nên trở về đúng nếu ...

  • Các loại giống hệt nhau
  • Một loại là phụ huynh (ngay lập tức hay cách khác) của người kia
  • Hai loại có cùng cha mẹ ngay lập tức

Bạn có thể sử dụng

private bool AreSame(Type a, Type b) 
{ 
    if(a == b) return true; // Either both are null or they are the same type 

    if(a == null || b == null) return false; 

    if(a.IsSubclassOf(b) || b.IsSubclassOf(a)) return true; // One inherits from the other 

    return a.BaseType == b.BaseType; // They have the same immediate parent 
} 
+0

mẫu và giải thích tuyệt vời. +1 –

+0

Tôi ước có một cách để chia sẻ câu trả lời được chấp nhận. Thx lần nữa. –

+0

@Adam: Tôi tự hỏi không có cách nào kết hợp cả hai cách tiếp cận của chúng tôi. Bạn có thể giữ một danh sách các kiểu kết quả từ việc lấy BaseType.GetType() trên cả a và b cho đến khi bạn (1) đạt đến System.Object (hoặc một số loại có hạn chế hơn) [thất bại] hoặc (2) có một kết quả phù hợp [ vượt qua]. –

2

Tôi đã thử những điều sau đây với cấu trúc phân cấp sử dụng cả giao diện và lớp bê tông. Nó đi lên chuỗi lớp cơ sở cho một trong các loại cho đến khi nó đạt đến "đối tượng" mà tại đó chúng tôi kiểm tra xem loại đích hiện tại có thể gán cho loại nguồn không. Chúng tôi cũng kiểm tra xem các loại có giao diện chung hay không. nếu họ làm vậy thì họ 'AreSame'

Hy vọng điều này sẽ hữu ích.

public interface IUser 
{ 
    int ID { get; set; } 
    string Name { get; set; } 
} 

public class NetworkUser : IUser 
{ 
    public int ID 
    { 
     get; 
     set; 
    } 

    public string Name 
    { 
     get; 
     set; 
    } 
} 

public class Associate : NetworkUser,IUser 
{ 
    #region IUser Members 

    public int ID 
    { 
     get; 
     set; 
    } 

    public string Name 
    { 
     get; 
     set; 
    } 

    #endregion 
} 

public class Manager : NetworkUser,IUser 
{ 
    #region IUser Members 

    public int ID 
    { 
     get; 
     set; 
    } 

    public string Name 
    { 
     get; 
     set; 
    } 

    #endregion 
} 


public class Program 
{ 

    public static bool AreSame(Type sourceType, Type destinationType) 
    { 
     if (sourceType == null || destinationType == null) 
     { 
      return false; 
     } 

     if (sourceType == destinationType) 
     { 
      return true; 
     } 

     //walk up the inheritance chain till we reach 'object' at which point check if 
    //the current destination type is assignable from the source type  
    Type tempDestinationType = destinationType; 
     while (tempDestinationType.BaseType != typeof(object)) 
     { 
      tempDestinationType = tempDestinationType.BaseType; 
     } 
     if(tempDestinationType.IsAssignableFrom(sourceType)) 
     { 
      return true; 
     } 

     var query = from d in destinationType.GetInterfaces() join s in sourceType.GetInterfaces() 
        on d.Name equals s.Name 
        select s; 
     //if the results of the query are not empty then we have a common interface , so return true 
    if (query != Enumerable.Empty<Type>()) 
     { 
      return true; 
     } 
     return false;    
    } 

    public static void Main(string[] args) 
    { 

     AreSame(new Manager().GetType(), new Associate().GetType()); 
    } 
} 
+0

thx cho mã. +1 –

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