Технический обзор - пропустить этот ответ .
Для распространенных случаев, когда происходит копирование - пропустить этот ответ .
Копирование elision - это оптимизация, выполняемая большинством компиляторов для предотвращения дополнительных (потенциально дорогостоящих) копий в определенных ситуациях. Он делает возвращение по значению или пропускной способностью практически осуществимым (применяются ограничения).
Это единственная форма оптимизации, которая исключает (ha!) Правило as-if - копирование может применяться даже если копирование / перемещение объекта имеет побочные эффекты.
Следующий пример, взятый из Wikipedia :
struct C {
C() {}
C(const C&) { std::cout << "A copy was made.\n"; }
};
C f() {
return C();
}
int main() {
std::cout << "Hello World!\n";
C obj = f();
}
В зависимости от компилятора & amp; все допустимые значения:
Hello World! Была сделана копия. Была сделана копия.
Hello World! Копия была сделана.
Hello World!
Это также означает, что можно создавать меньше объектов, t полагаться на определенное количество вызываемых деструкторов. Вы не должны иметь критической логики внутри copy / move-constructors или destructors, так как вы не можете полагаться на их вызываемые.
Если вызов конструктора копирования или перемещения отменяется, этот конструктор должен все же существуют и должны быть доступны. Это гарантирует, что копирование не позволяет копировать объекты, которые обычно не могут быть скопированы, например. потому что у них есть частный или удаленный конструктор copy / move.
C ++ 17: Начиная с C ++ 17, Copy Elision гарантируется, когда объект возвращается напрямую:
struct C { C() {} C(const C&) { std::cout << "A copy was made.\n"; } }; C f() { return C(); //Definitely performs copy elision } C g() { C c; return c; //Maybe performs copy elision } int main() { std::cout << "Hello World!\n"; C obj = f(); //Copy constructor isn't called }
С тех пор aa
набор/объект, который мог бы быть пустым, можно ли проверить aa == null
?
(aa
/ xx
могло бы быть взаимозаменяемым (опечатка в вопросе); исходные переговоры по вопросу [приблизительно 118], но только определяют aa
)
т.е.
select new {
AssetID = x.AssetID,
Status = aa == null ? (bool?)null : aa.Online; // a Nullable<bool>
}
или если Вы хотите, чтобы значение по умолчанию было false
(не null
):
select new {
AssetID = x.AssetID,
Status = aa == null ? false : aa.Online;
}
<час> Обновление; в ответ на downvote я занялся расследованиями больше..., факт, это - правильный подход! Вот пример на Northwind:
using(var ctx = new DataClasses1DataContext())
{
ctx.Log = Console.Out;
var qry = from boss in ctx.Employees
join grunt in ctx.Employees
on boss.EmployeeID equals grunt.ReportsTo into tree
from tmp in tree.DefaultIfEmpty()
select new
{
ID = boss.EmployeeID,
Name = tmp == null ? "" : tmp.FirstName
};
foreach(var row in qry)
{
Console.WriteLine("{0}: {1}", row.ID, row.Name);
}
}
И вот TSQL - в значительной степени, что мы хотим (это не ISNULL
, но это достаточно близко):
SELECT [t0].[EmployeeID] AS [ID],
(CASE
WHEN [t2].[test] IS NULL THEN CONVERT(NVarChar(10),@p0)
ELSE [t2].[FirstName]
END) AS [Name]
FROM [dbo].[Employees] AS [t0]
LEFT OUTER JOIN (
SELECT 1 AS [test], [t1].[FirstName], [t1].[ReportsTo]
FROM [dbo].[Employees] AS [t1]
) AS [t2] ON ([t0].[EmployeeID]) = [t2].[ReportsTo]
-- @p0: Input NVarChar (Size = 0; Prec = 0; Scale = 0) []
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 3.5.30729.1
ЧТО И ТРЕБОВАЛОСЬ ДОКАЗАТЬ?
Можно использовать ??
оператор для установки значения по умолчанию, но сначала необходимо установить Nullable
свойство к true
в Вашем файл dbml в обязательном поле (xx.Online
)
var hht = from x in db.HandheldAssets
join a in db.HandheldDevInfos on x.AssetID equals a.DevName into DevInfo
from aa in DevInfo.DefaultIfEmpty()
select new
{
AssetID = x.AssetID,
Status = xx.Online ?? false
};
Похож на тип, булевская переменная и поэтому никогда не может быть пустым и должна быть ложь по умолчанию.
У меня часто возникают проблемы с последовательностями (в отличие от дискретных значений). Если у меня есть последовательность целых чисел, и я хочу их СУММИТЬ, когда список пуст, я получу сообщение об ошибке «InvalidOperationException: нулевое значение не может быть присвоено члену с типом System.Int32, который не может быть нулевым значением. тип.".
Я обнаружил, что могу решить эту проблему, приведя последовательность к типу, допускающему значение NULL. SUM и другие агрегатные операторы не выдают эту ошибку, если последовательность типов, допускающих значение NULL, пуста.
Например, что-то вроде этого
MySum = MyTable.Where(x => x.SomeCondtion).Sum(x => x.AnIntegerValue);
превращается
MySum = MyTable.Where(x => x.SomeCondtion).Sum(x => (int?) x.AnIntegerValue);
Второй вернет 0, если ни одна строка не соответствует предложению where. (первый выдает исключение, когда строки не совпадают).