views:

190

answers:

4
db.Albums.FirstOrDefault(x => x.OrderId == orderId)

or

db.Albums.FirstOrDefault(x => x.OrderId.Equals(orderId))
+7  A: 

They will both be equivalent from a performance perspective. I tend to prefer == over .Equals() for readability, but the beauty of L2S is that you can use either one, depending on what type of object you have.

(And I'm assuming your second statement is on the orderId, and not the order object)

Dave Markle
I haven't done C# in years, but isn't this an autoboxing thing, and not an L2S thing? Or does the `==` depend on the instance at hand?
Yar
@yar: Nothing's being boxed, it's an expression tree that's visited and transformed into a SQL query.
Aaronaught
@Aaronaught, yes, I see that now, wish I had looked at the code a bit more carefully :) At the same time, I'll have to read up on expression trees, because I thought the "param" would get evaluated before FirstOrDefault even gets it. Apparently that's not right.
Yar
+8  A: 

I'm going to try to convince you that:

  • The two methods you proposed give the same performance.
  • There are at least two non-performance related reasons you should prefer ==.
  • There is another separate improvement that you can make to your code to reduce the possibility of errors.

To see that the performance will be the same, look at the SQL generated in each case. This test program shows you how you can view the generated 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();

The SQL sent in each case is the same, as you can see by inspecting the log:

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

Regarding whether to use == or Equals, firstly I'd suggest using == for readability. This is the idiomatic way to compare two integers in C#.

Secondly with == you will get a compile time error if you give objects of different (incompatible) types. I assume that in your case order has type int, but let's assume that someone else wrote this code and accidentally made an error where order is a variable of type Order instead of an int. Now let's compare what would happen in each case:

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'

It is better to get compile time errors than runtime errors, so prefer to use == in this case.

Finally, if you only expect one result you should prefer to use SingleOrDefault instead of FirstOrDefault as the former will throw an exception if there are two matching objects found instead of just returning the first. This extra check will cost a tiny amount in performance but again allows you to catch errors earlier. If performance is a critical issue for you, instead of removing these safety checks you should consider fetching multiple objects from the database at once, not one object at a time.

So in summary I recommend that you use this:

Album album = db.Albums.SingleOrDefault(x => x.OrderId == orderId);
Mark Byers
i mean that order has int type
msony
Good point on .Equals() being too permissive with types!
Dave Markle
+1 Great answer Mark!
Philip Daubmeier
+1  A: 

In most situations you should get the same result. However, there is a difference.

Using the operator Equals determines whether two Object instances are the same. The operator == determines whether two Objects have the same value.

In this case, I use the == operator, so it's more readable.

Tim
+1 Good Point. If the OrderId in the DB is null, will this L2S translate to `x.Order == null`? If so the `.Equals` call will fail as there is no valid object on the left hand side.
Binary Worrier
`Int32`, `Guid`, and all the other value types/primitives have `Equals` overloads that take arguments of the same type. The only instance when this would produce a different result is if the `orderId` argument is actually a different type from the `Order.OrderId` property.
Aaronaught
This is wrong: The Equals method is marked virtual on System.Object, and can be overriden. It should do the same as ==.
Arjan Einbu
@Arjan EinbuYour statement is partially correct.When using the == operator, the String class uses the static Equals method internally. This method first uses the == operator to check if the strings are the same object. This is equal to using the Object.ReferenceEquals method.If neither of the strings are null, the static Equals method calls the instance method Eqauls on the string to the left of the operator and passes the string to the right of the operator as a parameter to perform a string compare.
Tim
A: 

It's almost same. If you want to check only the value then you should use

==

If you want check the value as well as if they are same instances or not use

Equals

But in both cases resulting time is almost same.

Johnny
`Equals` does not imply reference equality. It *may* perform a reference check when the arguments are both reference types, but it is largely the same as `==` in that respect. If you want reference equality then you use the `object.ReferenceEquals` method.
Aaronaught