Основное различие в ваших 2 примерах состоит в том, что в class A
всякий раз, когда вы определяете переменную как T, вы можете использовать все свойства / функции для этой переменной, которые также определены в IFoo.
Однако в class B
IFoo
- это просто имя для параметра универсального типа, и поэтому всякий раз, когда вы объявляете переменную внутри класса как IFoo
, вы можете использовать ее только как тип object
. Например,
если
public interface IFoo
{
int Value { get; set; }
}
, то вы можете сделать это в class A
class A<T> where T : IFoo
{
public void DoSomething(T value)
{
value.Value++;
}
}
Если вы попробуете то же самое в class B
, вы получите ошибку компилятора, котораяIFoo
не содержит свойство Value
или что-то подобное.Причина в том, что <IFoo>
в классе B является просто именем и не имеет отношения к интерфейсу, вы могли бы назвать его как угодно.
Обновление:
class B {
private IFoo foo;
B(IFoo foo) { this.foo = foo; }
/* etc */
}
Эта конструкция действительно в основном та же самая, за исключением случаев, когда вы снова выставляете IFoo
обратно наружу. Рассмотрим следующее свойство в обоих классах
класса A:
public T Foo { get { return foo; }}
класса B:
public IFoo Foo { get { return foo; }}
Теперь рассмотрим, как вы инициализировали оба класса классом C, который определен как
public class FooClass : IFoo
{
public int Value { get; set; }
public int SomeOtherValue { get; set; }
}
, а затем рассмотрите две переменные, определенные как
var foo = new FooClass();
var a = new A<FooClass>(foo);
var b = new B(foo);
, чтобы установитьSomeOtherValue
используя a
вы можете сделать
a.Foo.SomeOtherValue = 2;
, в то время как для b вы должны сделать
((FooClass)b.Foo).SomeOtherValue = 2;
Надеюсь, что имеет смысл; -)