2010-05-13 2 views

ответ

7

Они оба будут эквивалентны с точки зрения производительности. Я предпочитаю использовать более .Equals() для удобочитаемости, но красота L2S заключается в том, что вы можете использовать любой из них, в зависимости от того, какой тип объекта у вас есть.

(И я предполагаю, что ваше второе утверждение находится на OrderId, а не объект заказа)

+0

Я не делал C# годами, но разве это не автообъект, а вещь L2S? Или '' '' зависит от экземпляра под рукой? –

+0

@yar: ничто не помещается в коробку, это дерево выражений, которое было посещено и преобразовано в SQL-запрос. – Aaronaught

+0

@ Я не знаю, да, я вижу, что теперь я хотел бы взглянуть на код немного осторожно :) В то же время мне придется читать на деревьях выражений, потому что я думал, что «param» будет оценен прежде чем FirstOrDefault даже получит его. Видимо, это неправильно. –

9

Я буду пытаться убедить вас в том, что:

  • Эти два метода, предложенный дают такую ​​же производительность.
  • Есть, по крайней мере, две причины, не связанные с производительностью, которые вы должны предпочесть ==.
  • Существует еще одно отдельное усовершенствование, которое вы можете внести в свой код, чтобы уменьшить вероятность ошибок.

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

int orderId = 4; 
TextWriter textWriter = new StringWriter(); 
using (var dc = new DataClasses1DataContext()) 
{ 
    dc.Log = textWriter; 
    Order o1 = dc.Orders.FirstOrDefault(x => x.OrderId == orderId); 
    Order o2 = dc.Orders.FirstOrDefault(x => x.OrderId.Equals(orderId)); 
} 
string log = textWriter.ToString(); 

SQL, послана в каждом случае является такой же, как вы можете видеть, проверив журнал:

SELECT TOP (1) [t0].[OrderId], [t0].[CustomerID], [t0].[Date], [t0].[Description] 
FROM [dbo].[Order] AS [t0] 
WHERE [t0].[OrderId] = @p0 

SELECT TOP (1) [t0].[OrderId], [t0].[CustomerID], [t0].[Date], [t0].[Description] 
FROM [dbo].[Order] AS [t0] 
WHERE [t0].[OrderId] = @p0 

относительно того, чтобы использовать == или Equals, во-первых, я бы предложил использовать == для удобства чтения. Это идиоматический способ сравнения двух целых чисел в C#.

Во-вторых с == вы получите ошибку времени компиляции, если вы даете объекты разных (несовместимых) типов. Я предполагаю, что в вашем случае order имеет тип int, но предположим, что кто-то еще написал этот код и случайно сделал ошибку, где order является переменной типа Order вместо int. Теперь давайте сравним, что произойдет в каждом конкретном случае:

Order order = new Order { OrderId = 4 }; 

x.OrderId.Equals(order) // This compiles, but you get an exception at runtime: 
         // Could not format node 'Value' for execution as SQL. 

x.OrderId == order  // Compile error: Operator '==' cannot be applied to 
         // operands of type 'int' and 'Order' 

Лучше ошибки компиляции времени, чем ошибки во время выполнения, поэтому предпочитают использовать == в этом случае.

Наконец, если вы ожидаете только одного результата, вы должны предпочесть использовать SingleOrDefault вместо FirstOrDefault, поскольку первый будет генерировать исключение, если есть два подходящих объекта вместо того, чтобы просто возвращать первый. Эта дополнительная проверка будет стоить крошечной суммы в производительности, но снова позволит вам ловить ошибки раньше. Если производительность является для вас важной проблемой, вместо удаления этих проверок безопасности вы должны сразу выбрать выборку из базы данных, а не по одному объекту за раз.

Так что в целом я рекомендую вам использовать это:

Album album = db.Albums.SingleOrDefault(x => x.OrderId == orderId); 
+0

Я имею в виду, что порядок имеет тип int – Sasha

+3

Хорошая точка .Equals() слишком разрешительная с типами! –

+0

+1 Отличный ответ Марк! –

1

В большинстве случаев вы должны получить тот же результат. Однако есть разница.

Использование оператора Equals определяет, являются ли два экземпляра объекта одинаковыми. Оператор == определяет, имеют ли два объекта одинаковое значение.

В этом случае я использую оператор ==, поэтому он более читабельен.

+3

+1 Хорошая точка. Если OrderId в БД имеет значение NULL, будет ли этот L2S перевести на 'x.Order == null'? Если это так, вызов '.Equals' завершится неудачно, так как в левой части нет действительного объекта. –

+0

'Int32',' Guid' и все другие типы значений/примитивы имеют перегрузки 'Equals', которые принимают аргументы одного типа. Единственный экземпляр, когда это приведет к другому результату, - это аргумент 'orderId' на самом деле другого типа из свойства' Order.OrderId'. – Aaronaught

+0

Это неправильно: метод Equals отмечен как виртуальный объект System.Object и может быть переопределен. Он должен делать то же самое, что и ==. –

0

Это почти то же самое. Если вы хотите проверить только значение, то вы должны использовать

==

Если вы хотите проверить значение, а также, если они одни и те же случаи, или не использовать

Equals

Но в обоих случаях результирующее время почти такое же.

+2

'Equals' не означает ссылки на равенство. Он * может * выполнять контрольную проверку, когда аргументы являются и ссылочными типами, но в основном это совпадает с '=='. Если вам требуется ссылочное равенство, вы используете метод 'object.ReferenceEquals'. – Aaronaught