2015-09-19 2 views
2

Я новичок в Дженерики я начал изучать дженерики из MSDN LibraryНеограниченные параметры типа в Обобщения C#

Я не могу понять, ниже пунктов о параметрах неограниченными типа. Параметры

типа, которые не имеют никаких ограничений, таких, как T в public class SampleClass<T>{}, называются параметрами типа неограниченные. Параметры Неограниченные типа имеют следующие правила:

  • В != и == операторов не могут быть использованы, потому что нет никакой гарантии, что конкретного типа аргумент будет поддерживать эти операторы.
  • Вы можете сравнить с null. Если неограниченный параметр сравнивается с null, сравнение всегда будет возвращать false, если аргумент типа равен тип значения.

Я не нашел примеров вышеуказанных пунктов. Будет здорово, если кто-нибудь даст мне пример, чтобы понять моменты.

Примечание: Мой вопрос об использовании != и == операторов ... почему мы не можем использовать эти операторы в неограниченном типе и поэтому всегда возвращать false если Неограниченные параметр сравниваются с null

+0

Обратите внимание, что приведенная вами документация фактически неверна. 'default (T) == null' возвращает true, когда' T' является нулевым значением типа типа 'int?'. –

ответ

0

Типа параметры могут иметь ограничения, например: where T: BaseClass. Это означает, что T должен быть унаследован от BaseClass. Если таких ограничений для параметра типа нет, он называется неограниченным.

0

Там в 2 балла из документации, которую вы цитируемой:

= и == операторы не могут быть использованы, потому что нет никакой гарантии, что конкретный тип аргумента будет поддерживать эти операторы.

Это означает, что компилятор не может знать, что тип T имеет операторы == и !=. A SampleClass<int> будет работать, но SampleClass<MyType> не может, если MyType не реализовал операторов. Поскольку T неограничен, это означает, что компилятор не знает, чего ожидать, поэтому он должен принять наиболее ограничительный случай.

Вы можете сравнить с NULL. Если неограниченный параметр сравнивается с нулем, сравнение всегда будет возвращать false, если аргумент type является типом значения.

Это просто указывает на то, что вы можете сравнить с NULL, но если T является непустым типом, то он всегда возвращает false. Рассмотрим следующий пример:

int i = 0; 
if (null == i) 
{ 
} 

Это будет генерировать предупреждения компилятора, так как нет никакого значения вы можете дать i сделать выражение true.

4

Давайте предположим, что для второго это было возможно:

public class C 
{ 
    public bool AreEqual<T>(T first, T second) 
    { 
      return first == second; 
    } 
} 

теперь предполагают struct под названием F, который не имеет реализации == оператора (который не структура не имеет по умолчанию). Что должно случиться здесь?

F first = new F(); 
F second = new F(); 
var c = new C(); 
Console.WriteLine(c.AreEqual(first, second)); 

Тип значения не имеет реализации ==, и мы не можем отложить до Object.ReferenceEquals, так как это, опять же, тип значения. Вот почему компилятор не позволяет вам это делать.

+0

Я попробую и дам вам знать. Можем ли мы использовать 'Equals()' вместо '=='? –

+0

'Equals' в типе значений, который не реализует' IEquatable', вызовет 'Object.ReferenceEquals', который будет полем. –

+0

@ Хуррам превращает равенство в не имеющий отношения к делу. –

0

Мой вопрос об использовании! = И == операторы ... почему мы не можем использовать эти операторы в неограниченном типа

Что они означают? Обычно != и == означает «не равно» и «равно», но точное значение этого зависит от того, являются ли они типами значений или ссылочными типами (и перегружали ли они эти операторы, но это также не относится ко многим ограниченные типы). Без ограничений, по крайней мере, один из тех != и == не имеет значения.

и почему всегда возвращать false, если параметр Unbounded сравнивается с NULL.

Вы неправильно читаете. Что на самом деле сказал, и цитируемый вами ранее, является:

сравнение всегда будет возвращать ложные если аргумент типа является типом значения. [Выделено мной]

Это фактически неверно, тип обнуляемым значение может вернуть true в этом случае:

public class Test<T> 
{ 
    public bool IsNull(T val) 
    { 
    return val == null; 
    } 
} 

С выше коде, мы получаем true если мы называем new Test<int?>().IsNull(null) и ложным, если мы называем new Test<int?>().IsNull(1).

С любым типом значения, отличным от Nullable, мы получаем false, потому что это единственное возможное значение; значения, отличные от Nullable<T>, не могут быть равны нулю.

Следует отметить, что джиттер будет предугадать это, поскольку при выдаче машинного кода для метода он будет знать, что val == null всегда является ложным и заменяет код константой false. Если есть ветка, то она не должна быть закорочена. Рассмотрим:

public string CallToString(T val) 
{ 
    if (val == null) 
    return null; 
    else 
    return val.ToString(); 
} 

Когда это JITted для T, который не является обнуляемого тип значения, то это то же самое, как если бы код был:

public string CallToString(T val) 
{ 
    return val.ToString(); 
} 

Поскольку джиттера знает первую ветвь никогда не ударят. Аналогичным образом рассмотрим Enumerable.Max(). Этот метод возвращает null в пустых последовательностях, имеющих тип NULL, и в противном случае выбрасывает исключение.Для конкретных переопределений это просто: Enumerable.Max(this IEnumerable<decimal?> source), например, имеет код для возврата null в этом случае и Enumerable.Max(this IEnumerable<decimal> source) код для броска. Однако для общего случая он должен охватывать оба случая. Он делает это таким образом:

public static TSource Max<TSource>(this IEnumerable<TSource> source) 
{ 
    if (source == null) throw Error.ArgumentNull("source"); 
    Comparer<TSource> comparer = Comparer<TSource>.Default; 
    TSource value = default(TSource); 
    if (value == null) 
    { 
    using (IEnumerator<TSource> e = source.GetEnumerator()) 
    { 
     do 
     { 
     if (!e.MoveNext()) return value; 
     value = e.Current; 
     } while (value == null); 
     while (e.MoveNext()) 
     { 
     TSource x = e.Current; 
     if (x != null && comparer.Compare(x, value) > 0) value = x; 
     } 
    } 
    } 
    else 
    { 
    using (IEnumerator<TSource> e = source.GetEnumerator()) 
    { 
     if (!e.MoveNext()) throw Error.NoElements(); 
     value = e.Current; 
     while (e.MoveNext()) 
     { 
     TSource x = e.Current; 
     if (comparer.Compare(x, value) > 0) value = x; 
     } 
    } 
    } 
    return value; 
} 

Когда JITted для обнуляемого типа (ссылка типа Nullable<T> джиттера зная заранее, что default(TSource) == null всегда верно означает, что это то же самое, как если бы он был jitting:

public static TSource Max<TSource>(this IEnumerable<TSource> source) 
{ 
    if (source == null) throw Error.ArgumentNull("source"); 
    Comparer<TSource> comparer = Comparer<TSource>.Default; 
    TSource value = null; 
    using (IEnumerator<TSource> e = source.GetEnumerator()) 
    { 
    do 
    { 
     if (!e.MoveNext()) return value; 
     value = e.Current; 
    } while (value == null); 
    while (e.MoveNext()) 
    { 
     TSource x = e.Current; 
     if (x != null && comparer.Compare(x, value) > 0) value = x; 
    } 
    } 
    return value; 
} 

в то время как, если тип аа ненулевое значение, то тип это то же самое, как если бы он был jitting:

public static TSource Max<TSource>(this IEnumerable<TSource> source) 
{ 
    if (source == null) throw Error.ArgumentNull("source"); 
    Comparer<TSource> comparer = Comparer<TSource>.Default; 
    TSource value = default(TSource); 
    using (IEnumerator<TSource> e = source.GetEnumerator()) 
    { 
    if (!e.MoveNext()) throw Error.NoElements(); 
    value = e.Current; 
    while (e.MoveNext()) 
    { 
     TSource x = e.Current; 
     if (comparer.Compare(x, value) > 0) value = x; 
    } 
    } 
    return value; 
} 

в качестве такого факта, что == между невообразимым типом значений и null всегда false!= всегда true) - это не просто ограничение, оно действительно может быть полезно для того, чтобы мы могли по-разному охватывать типы с нулевым и непустым значением, а джиттер будет вести себя разумно при удалении ветки, которая не используется в конкретном случае.

Смежные вопросы