Ключевое слово Linq "равно"
Будет ли ключевое слово "равно" в LINQ проверять наличие объектов слева и справа, указывать на одну и ту же память или проверять их содержимое?
4 ответа
Сравнивает значения.
Также см. Linq: В чем разница между == и равно в соединении?
Это зависит от объекта. Если это тип значения, обычно сравниваются значения, это ссылочный тип, ссылки сравниваются, если только метод Equals() не переопределен.
Из MSDN:
Реализация по умолчанию Equals поддерживает равенство ссылок для ссылочных типов и побитовое равенство для типов значений. Равенство ссылок означает, что сравниваемые ссылки на объекты ссылаются на один и тот же объект. Побитовое равенство означает, что сравниваемые объекты имеют одинаковое двоичное представление.
Обратите внимание, что производный тип может переопределять метод Equals для реализации равенства значений.
"Равно" в запросе на соединение использует компаратор равенства по умолчанию для сравнения ключей с использованием поиска по ключам. Объединение реализовано в Enumerable.Join, и ключ может быть либо значением, либо ссылкой. При запросе с использованием Linq для Sql ключ обычно является значением, поскольку первичные ключи обычно отображаются на типы значений. Однако, как показано в следующем коде, сравнение равно может быть либо по значению, либо по ссылке, которая всегда подходит для типа ключа:
KeyObj k1 = new KeyObj(); k1.Id = 1001;
KeyObj k2 = new KeyObj(); k2.Id = 1002;
KeyObj k3 = new KeyObj(); k3.Id = 1003;
KeyObj k4 = new KeyObj(); k4.Id = 1004;
KeyObj k5 = new KeyObj(); k4.Id = 1005;
List<Foo> foos =
new List<Foo>()
{
new Foo("o1",k1),
new Foo("o2",k2),
new Foo("o4",k5)
};
List<Bar> bars =
new List<Bar>()
{
new Bar("o2",k1),
new Bar("o3",k2),
new Bar("o4",k4),
new Bar("o5",k5)
};
var foobar = from f in foos
join b in bars on f.Ko equals b.Ko
select f.Name + " in foos joined by reference with " + b.Name + " in bars ";
foreach (var v in foobar)
{
Debug.WriteLine(v);
}
foobar = from f in foos
join b in bars on f.Name equals b.Name
select f.Name + " in foos joined by value with " + b.Name + " in bars ";
foreach (var v in foobar)
{
Debug.WriteLine(v);
}
class KeyObj { public int Id { get; set; } }
class Foo : Base
{
public Foo(string s, KeyObj ko) : base(s, ko) { }
}
class Bar : Base
{
public Bar(string s, KeyObj ko) : base(s, ko) { }
}
class Base
{
string _name = "";
public string Name { get { return _name; }}
KeyObj _ko = null;
public KeyObj Ko { get { return _ko; }}
public Base(string s, KeyObj ko)
{
_name = s;
_ko = ko;
}
}
Выход из этого:
o1 в foos соединяется ссылкой с o2 в барах
o2 в foos соединяется ссылкой с o3 в барах
o4 в foos соединяется ссылкой с o5 в барах
o2 в foos объединяется по значению с o2 в барах
o4 в foos объединяется по значению с o4 в барах
Из MSDN: http://msdn.microsoft.com/en-us/library/bb311040.aspx
Оператор равенства
Предложение соединения выполняет эквиджоин. Другими словами, вы можете основывать совпадения только на равенстве двух ключей. Другие типы сравнений, такие как "больше чем" или "не равно", не поддерживаются. Чтобы прояснить, что все объединения являются равносильными, в предложении объединения используется ключевое слово equals вместо оператора ==. Ключевое слово equals может использоваться только в предложении объединения, и оно отличается от оператора == одним важным способом. При равенстве левая клавиша потребляет последовательность внешнего источника, а правая клавиша потребляет внутренний источник. Внешний источник находится только в области видимости с левой стороны от equals, а внутренний источник последовательности находится только в области видимости справа.