interface IBar { void Hidden(); }
class Foo : IBar { public void Visible() { /*...*/ } void IBar.Hidden() { /*...*/ } }
class Program
{
static T CallHidden1<T>(T foo) where T : Foo
{
foo.Visible();
((IBar)foo).Hidden(); //Cast required
return foo;
}
static T CallHidden2<T>(T foo) where T : Foo, IBar
{
foo.Visible();
foo.Hidden(); //OK
return foo;
}
}
Есть ли какое-либо различие (CallHidden1 по сравнению с CallHidden2) фактический скомпилированный код? Есть ли другие различия между где T: Foo и где T: Foo, IBar (если Foo реализует IBar), это в доступе к явно реализованным интерфейсным участникам?
Сгенерированный IL немного отличается:
L_000d: ldarg.0
L_000e: box !!T
L_0013: callvirt instance void WindowsFormsApplication1.IBar::Hidden()
vs.
L_000d: ldarga.s foo
L_000f: constrained !!T
L_0015: callvirt instance void WindowsFormsApplication1.IBar::Hidden()
Если бы T
был типом значения, это привело бы к заключению foo
в CallHidden1
, но не в CallHidden2
. Однако, поскольку Foo
является классом, любой тип T
, производный от Foo
, не будет типом значения, и, следовательно, поведение будет идентичным.
var doIt = function() {
$("div.my").text("My message");
}
setTimeout(doIt, 3000);
-121--1712641- при использовании jQuery 1.4 всегда можно выполнить следующие действия:
$ (функция () {
$ ('# divId') .delay (3000) .text ('Новый текст');
});
Да, крошечный бит, так как второй указывает, что интерфейс должен быть реализован, что может стать важным, если позже Foo
будет изменен так, что он не реализует IBar
.
Это делает его непригодным для использования в CallHidden2 < >
, оставаясь действительным во время компиляции для CallHidden1 < >
(что приведет к сбою во время выполнения, если IBar
больше не будет реализован Foo
).
Таким образом, если они находятся в отдельных сборках, различные метаданные будут иметь значение. Исполняемый IL, однако, будет довольно похож, если не тот же самый.