Если Вы вставляете в единственную таблицу, можно записать запрос как это (возможно, только в MySQL):
INSERT INTO table1 (First, Last)
VALUES
('Fred', 'Smith'),
('John', 'Smith'),
('Michael', 'Smith'),
('Robert', 'Smith');
Это оператор ==
.
Класс TimeSpan
содержит перегрузку оператора равенства:
public static bool operator ==(DateTime d1, DateTime d2)
{
return (t1._ticks == t2._ticks);
}
Само по себе это не " t делают возможным сравнение с null
, , но ...
С появлением типов, допускающих значение NULL, каждая структура неявно преобразуется в свой тип, допускающий значение NULL , поэтому, когда вы видите что-то вроде
TimeSpan y = new TimeSpan();
if (y == null)
return;
, вы не видите , что это происходит:
TimeSpan y = new TimeSpan();
if ((Nullable<TimeSpan>)y == (Nullable<TimeSpan>)null)
return;
Null получает неявное преобразование (неявное присвоение?), но не все Система .Object
объекты делают:
TimeSpan y = new TimeSpan();
object o = null;
if (y == o) //compiler error
return;
Хорошо, но оператор равенства не принимает аргументы, допускающие значение NULL, не так ли?
Что ж, здесь может помочь msdn , заявив:
Предопределенные унарные и двоичные операторы и любые определяемые пользователем операторы, существующие для типов значений также может использоваться типами, допускающими значение NULL. Эти операторы производят нулевое значение если [любой из] операндов равен нулю; иначе, оператор использует содержащееся значение для вычисления результата.
Таким образом, вы фактически получаете реализацию, допускающую значение NULL, для каждого оператора бесплатно с фиксированным определенным поведением. Упомянутое выше «содержащееся значение» - это фактическое значение, которое вернет оператор, не допускающий значения NULL.
Эта проблема эффективно возникла, когда были включены типы, допускающие значение NULL. Существует неявное преобразование из TimeSpan
в TimeSpan?
, и есть сравнение между TimeSpan?
и нулевым значением этого типа.
Компилятор выдает предупреждение для некоторых типов, которое проясняет, что он пытается сделать:
int x = 10;
if (x == null)
{
Console.WriteLine();
}
Дает это предупреждение:
Test.cs(9,13): warning CS0472: The result of the expression is always 'false'
since a value of type 'int' is never equal to 'null' of type 'int?'
Я считаю, что Марк Гравелл и я разработали обстоятельства, при которых предупреждение выдается один раз ... жаль, что это не соответствует .
Этот случай для дженериков рассматривается в разделе 7.9.6 спецификации языка C #.
Конструкция x == null разрешена, даже если T может представлять тип значения, а результат просто определяется как false, когда T является типом значения.
Я немного покопался в спецификации и не смог ' Я не найду более общего правила. Ответ Джона указывает на то, что это проблема с продвижением, допускающая значение NULL.
Это правило (или аналогичный вариант), похоже, здесь применяется. Если вы внимательно посмотрите на отраженный результат, вы заметите, что сравнения нет. Компилятор C #, очевидно, оптимизирует это сравнение и заменяет его на false.
Например, если вы наберете следующее
var x = new TimeSpan();
var y = x == null;
Console.WriteLine(x);
Затем декомпилируете его, вы увидите следующее
var x = new TimeSpan();
var y = false;
Console.WriteLine(x);
См. Также: C # 3 (.NET 3.5) версия csc не сообщает CS0162 о невозможности получения кода (struct / null)
Начиная с компилятора C # 3, что означает иногда даже не предупреждает вас об этом ;-p
Поскольку Guid
/ TimeSpan
и т.д. предоставляют ==
, они попадают в эту ловушку, где не Не предупреждаю.
Я НАШЕЛ ЭТО :)
Следующее дает предупреждение:
int i = 0;
if (i == null)
// ^^ Warning: The result of the expression is always 'false' since a value of
// type 'int' is never equal to 'null' of type 'int?'
Компилятор просто не может правильно выдать предупреждение о том, что null
вы typed был преобразован в тип TimeSpan?
для сравнения.
Изменить: соответствующий раздел в спецификации - §13.7.1, в котором говорится, что null
может быть неявно преобразован в любой тип, допускающий значение NULL , и (очень трудный для чтения) раздел §13.7.2, в котором указывается, что тип значения T
может быть неявно преобразован в T?
.
Первоначально я писал:
Что бы ни происходило, это что-то в спецификации C #, потому что, как говорит JaredPar, он компилируется просто с false
.
Обратите внимание, что это не компилируется:
TimeSpan ts = new TimeSpan();
object o = null;
if (ts == o) // error, Operator '==' cannot be applied to operands of type 'System.TimeSpan' and 'object'
...