Kiểm tra nếu đối tượng thực hiện giao diện


355

Cách kiểm tra đơn giản nhất nếu một đối tượng thực hiện giao diện đã cho trong C # là gì? (Trả lời câu hỏi này bằng Java )

Câu trả lời:


570
if (object is IBlah)

hoặc là

IBlah myTest = originalObject as IBlah

if (myTest != null)

85
+1 Cái thứ hai tốt hơn bởi vì có thể bạn sẽ cần phải phân vai sau đó với cái thứ nhất, do đó cung cấp cho bạn hai phôi ("là" và sau đó là một diễn viên rõ ràng). Với cách tiếp cận thứ hai, bạn chỉ đúc một lần.
Andrew Hare

51
@Andrew: +1; Thời gian một lần nữa cho liên kết đến bài viết blog Double-Casting AntiPotype cổ điển của Julian M Bucknall .
Jeroen Wiert Pluimers 17/03/2016

1
Tối ưu hóa có lẽ bạn sẽ không sử dụng hai lần trong trường hợp đầu tiên?
BuZz

1
@Joreen, liên kết đó bỏ lỡ một điểm nếu bạn đang làm việc với cấu trúc mà bạn không thể sử dụng "as" bởi vì nó không giữ null, đó là điều mà "as" cố gắng quay lại, trong trường hợp đó bạn phải trải qua một nullable lớp như int?, mặc dù không phải là vấn đề nếu bạn chỉ làm việc ở cấp giao diện vì chúng luôn là kiểu tham chiếu
MikeT

46
Kể từ C # 6.0:if (object is IBlah iblah) { iblah.SomeMethod(); }
Knelis

224

Sử dụng ishoặc astoán tử là cách chính xác nếu bạn biết loại giao diện tại thời gian biên dịch và có một phiên bản của loại bạn đang kiểm tra. Một cái gì đó mà không ai khác dường như đã đề cập là Type.IsAssignableFrom:

if( typeof(IMyInterface).IsAssignableFrom(someOtherType) )
{
}

Tôi nghĩ rằng điều này gọn gàng hơn nhiều so với việc xem qua mảng được trả về GetInterfacesvà cũng có lợi thế làm việc cho các lớp.


Tôi đang cố gắng xác định xem một loại có thực hiện một số khởi tạo IList hay không. Tôi đang sử dụng "typeof (IList <>). IsAssignableFrom (someType)" nhưng không được.
Bàn

3
Bạn có thể tốt hơn nên hỏi điều này trong một câu hỏi khác. Nếu someType là loại phần tử danh sách bạn có thể cần typeof (IList <>). MakeGenericType (someType). Nếu someType là loại danh sách, bạn nên xem Type.GetGenericArgument và Type.GetGenericTypeDefDef.
Andrew Kennan

Tôi sử dụng điều này để kiểm tra loại trong một hệ thống plugin. Nó có thể được sử dụng trong các tình huống mà một thể hiện của đối tượng chưa tồn tại. Nhưng tôi sử dụng cả phong cách này và Robert tùy thuộc vào những gì tôi đang làm nên tôi đã bỏ phiếu theo cả hai cách.
James

Đây là một nhận xét cũ hơn, nhưng để trả lời câu hỏi của @ Steenreem, hãy sử dụng typeof(IList).IsAssignableFrom(someType)mà không cần <>.
sốt

Phương thức này thậm chí hoạt động với các toán tử chuyển đổi và nếu TypeConverters có liên quan
Harald Coppoolse

22

Ví dụ:

if (obj is IMyInterface) {}

Dành cho lớp:

Kiểm tra nếu typeof(MyClass).GetInterfaces()chứa giao diện.


1
if (Array.IndexOf (typeof (MyClass) .GetInterfaces (), typeof (IMyInterface))! = -1) {...}
Constantin

2
hoặc: if (typeof (MyClass) .GetInterfaces (). Chứa (typeof (IMyInterface))) {...}
Lance Fisher

17

Nếu bạn muốn sử dụng đối tượng typecasted sau khi kiểm tra:
Vì C # 7.0:

if (obj is IMyInterface myObj)

Điều này giống như

IMyInterface myObj = obj as IMyInterface;
if (myObj != null)

Xem .NET Docs: Mẫu khớp với mẫu is# Type


16

Một biến thể về câu trả lời của @ AndrewKennan tôi đã sử dụng gần đây cho các loại thu được trong thời gian chạy:

if (serviceType.IsInstanceOfType(service))
{
    // 'service' does implement the 'serviceType' type
}

7

Đây bài viết là một câu trả lời tốt.

public interface IMyInterface {}

public class MyType : IMyInterface {}

Đây là một mẫu đơn giản:

typeof(IMyInterface).IsAssignableFrom(typeof(MyType))

hoặc là

typeof(MyType).GetInterfaces().Contains(typeof(IMyInterface))

3

Ngoài việc kiểm tra bằng toán tử "is", bạn có thể trang trí các phương thức của mình để đảm bảo rằng các biến được truyền cho nó thực hiện một giao diện cụ thể, như vậy:

public static void BubbleSort<T>(ref IList<T> unsorted_list) where T : IComparable
{
     //Some bubbly sorting
}

Tôi không chắc chắn phiên bản nào của .Net này đã được triển khai để có thể không hoạt động trong phiên bản của bạn.


2
.net 2.0 thêm thuốc generic.
Robert C. Barth

Đây là kiểm tra thời gian biên dịch duy nhất trong chủ đề này, cảm ơn.
Dustin Malone

2

Những gì làm việc cho tôi là:

Assert.IsNotNull(typeof (YourClass).GetInterfaces().SingleOrDefault(i => i == typeof (ISomeInterface)));


1

Gần đây tôi đã thử sử dụng câu trả lời của Andrew Kennan và nó không hiệu quả với tôi vì một số lý do. Tôi đã sử dụng điều này thay vào đó và nó hoạt động (lưu ý: viết không gian tên có thể được yêu cầu).

if (typeof(someObject).GetInterface("MyNamespace.IMyInterface") != null)

2
Nếu bạn kết thúc việc đi theo con đường này, tôi không phải là người hâm mộ chuỗi ma thuật, vì vậy tôi sẽ thay đổi tối thiểu thành loại này (IMyInterface) .Tên thay vì "MyNamespace.IMyInterface". Giúp đặt tên bằng chứng tái cấu trúc như một phần thưởng.
greyalien007

0

Tôi đã sử dụng

Assert.IsTrue(myObject is ImyInterface);

để kiểm tra trong bài kiểm tra đơn vị của tôi, bài kiểm tra myObject là một đối tượng đã triển khai giao diện ImyInterface của tôi.


-1

Tôi đã có một tình huống khi tôi chuyển một biến cho một phương thức và không chắc nó sẽ là một giao diện hay một đối tượng.

Các mục tiêu là:

  1. Nếu mục là một giao diện, khởi tạo một đối tượng dựa trên giao diện đó với giao diện là một tham số trong lệnh gọi của hàm tạo.
  2. Nếu mục đó là một đối tượng, hãy trả về null vì người đặt hàng cho các cuộc gọi của tôi đang mong đợi một giao diện và tôi không muốn mã được tăng.

Tôi đã đạt được điều này với những điều sau đây:

    if(!typeof(T).IsClass)
    {
       // If your constructor needs arguments...
       object[] args = new object[] { my_constructor_param };
       return (T)Activator.CreateInstance(typeof(T), args, null);
    }
    else
       return default(T);

-12

Điều này sẽ làm việc:

MyInstace.GetType().GetInterfaces();

Nhưng cũng tốt:

if (obj is IMyInterface)

Hoặc thậm chí (không thanh lịch):

if (obj.GetType() == typeof(IMyInterface))

9
Việc kiểm tra sự bằng nhau cho typeof (IMyInterface) sẽ luôn thất bại. Bị hạ bệ.
Jay Bazuzi

Đúng. Không có trường hợp nào của một giao diện.
Rauhotz
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.