2009-07-15 12 views
25

Kolega zadał mi dziś interesujące pytanie - czy słowo kluczowe C#/operator "jest" uważane za odbicie?C# "jest" operator - czy to odbicie?

object tmp = "a string"; 
if(tmp is String) 
{ 
} 

W jaki sposób operator jest realizowany za kulisami? Czy wymaga refleksji lub introspekcji? Czy z powodu silnie typowanej natury języka, typ obiektu jest natychmiast dostępny jako atrybut najwyższego poziomu obiektu w pamięci?

MSDN stwierdza:

Zauważ, że jest operator uzna tylko konwersje referencyjnych, konwersje bokserskie i Unboxing konwersji. Inne konwersje, takie jak konwersje zdefiniowane przez użytkownika, nie są uwzględniane przez operatora is.

Możliwość rozważenia konwersji pudełkowych i bezokiennych wydaje się sugerować mi jakąś introspekcję.

+0

powiązane http://stackoverflow.com/questions/57701/what-are-to-performance-characteristics-of-is-reflection-in-c?lq=1 – nawfal

Odpowiedz

31

Referencing ECMA-335 operator is generuje isinst Object Model IL instrukcji (Partycja III §4.6), które stanowi część instrukcji bazowej ustalonej w przeciwieństwie do bycia częścią biblioteki Odbicie (strefa IV §5.5).

Edytuj: Operator is jest niezwykle wydajny w porównaniu do biblioteki refleksów. można wykonać w zasadzie ten sam test znacznie wolniej poprzez refleksję:

typeof(T).IsAssignableFrom(obj.GetType()) 

Edit 2: Nie są prawidłowe o efektywności instrukcji (które już teraz edytowanych z urzędu) castclass i isinst. Są wysoce zoptymalizowane w każdej praktycznej implementacji VM. Jedynym problemem związanym z wydajnością jest możliwość wygenerowania wyjątku, który można uniknąć za pomocą operatora C# as i testu dla null (dla typów odniesienia) lub operatora is, a następnie rzutowania (dla typów wartości).

+0

Nic nie edytowałem, ale może powinienem wyjaśnić, co mam na myśli przez "drogi". Nie wiem zbyt wiele na temat wydajności IL, ale FxCop ma ostrzeżenie, jeśli twój kod do stworzenia, który emituje zarówno instrukcję isinst, jak i castclass, ponieważ uważają to za nieefektywne lub "kosztowne". –

+2

Jak już wspomniałem w drugiej edycji, powinieneś użyć 'as', po którym następuje kontrola' null' dla typów referencyjnych. Zamiast tego użyłeś 'is', po którym następuje rzutowanie, do czego ostrzega Cię FxCop. –

+2

Dla tego, co jest warte, w Compact Framework, IL, który musi jawnie sprawdzić RTTI (takie jak 'isinst' i' castclass') jest tak wolny jak odbicie, podczas gdy callvirt jest wysoce zoptymalizowany. Morał: staraj się unikać używania konstruktów typu case, w których mogą działać metody wirtualne/abstrakcyjne. –

5

Operator is zasadniczo określa, czy rzutowanie jest możliwe, ale zamiast rzucać wyjątek, gdy rzutowanie jest niemożliwe, zwraca false. Jeśli rozważasz rzucenie odbicia, to jest to również odbicie.

EDIT:

Po kilku badań odkryli, że obsada jest wykonywana w IL på instrukcją castclass natomiast is mapy operatorowi instrukcji isinst. FxCop ma rule, który ostrzega, jeśli wykonujesz niepotrzebne rzuty, najpierw używając instrukcji isinst, a następnie castclass. Mimo że operacje są wydajne, nadal mają one koszt wydajności.

+0

Operator "jest" zwraca true/false, a nie zero. – SolutionYogi

+1

Myślę, że myślisz o operatorze "jak" – Matt

+0

To, co opisałeś, to operator "jako". Operator "jest" jest zasadniczo tą samą operacją, tylko z inną wartością zwracaną. – Charlie

1

Inne języki mają informacje o czasie działania wystarczające do obsługi dynamicznego przesyłania, a jednak nic, co można by określić jako odbicie (C++ jest oczywistym przykładem).

Refleksja odnosi się do dodatkowych możliwości wykraczających poza samo odkrywanie typu obiektu. "Odbicie" obiektu oznacza na przykład możliwość chodzenia jego członków.

+0

Byłoby * bardziej * poprawne stwierdzenie, że odbicie analizuje elementy klasy, a nie obiektu, ponieważ nie trzeba mieć żywej instancji. Również refleksja pozwala "odkryć", jakie klasy masz w zespole, nie tylko członkowie i inne informacje o klasie. –

+0

@Danny Varod - Nie wszystkie języki mają klasy lub złożenia. –

+0

C++ ma klasy i biblioteki, Java ma klasy i pakiety. Programowanie obiektowe definiuje różnicę między obiektem a klasą. –