Мой вопрос об использовании! = И == операторы ... почему мы не можем использовать эти операторы в неограниченном типа
Что они означают? Обычно !=
и ==
означает «не равно» и «равно», но точное значение этого зависит от того, являются ли они типами значений или ссылочными типами (и перегружали ли они эти операторы, но это также не относится ко многим ограниченные типы). Без ограничений, по крайней мере, один из тех !=
и ==
не имеет значения.
и почему всегда возвращать 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
) - это не просто ограничение, оно действительно может быть полезно для того, чтобы мы могли по-разному охватывать типы с нулевым и непустым значением, а джиттер будет вести себя разумно при удалении ветки, которая не используется в конкретном случае.
Обратите внимание, что приведенная вами документация фактически неверна. 'default (T) == null' возвращает true, когда' T' является нулевым значением типа типа 'int?'. –