4

I understand that the C# keyword var implies the type at compile time and therefore requires the declaration and assignment in the same place, making the following construct illegal:

var something;

if (condition)
{
    something=1;
}
else
{
    something = 0;
}

Even though the C# compiler could principally determine that all assignments in the current scope result in the same type, it (presently) does not and therefore generates a compile time error.

In using var with LINQ, I sometimes want to initialize my result variable slightly differently depending on program conditions. The approach I have found is to use the ?: operator, as in:

var participants = (email == null ?
                   (from part in db.Participant
                    where part.SequenceNumber == seqNr
                    select part)
                   :
                   (from part in db.Participant
                    where part.EmailAddress == email
                    select part));

That works well enough if I just have two possible assignments, but quickly becomes unwieldy if there are multiple possible assignments.

Is there a more elegant approach to this?

Eric J.
  • 147,927
  • 63
  • 340
  • 553
  • Hmm, some languages allow the inference to be after the point of var declaration... – Dykam Jan 01 '10 at 00:06
  • It would surprise me if C# doesn't get more clever about type inference at some point. As long as all assignments in the current scope attempt to assign the same time, a compiler can handle this situation. – Eric J. Jan 01 '10 at 00:12
  • I agree that in principle this could be done, but it is rather more complicated in practice than your quick sketch would indicate. var not only requires that there be an initializer, it also requires that the initializer not refer to the variable. If you have int M(out int) then you can say "int x = M(out x);" but you cannot say "var x = M(out x);" because to do overload resolution on M, we need to know the type of x, which is what we're attempting to figure out. Would it be legal to say "var s; if (b) M(out s); else s = 0;" ? – Eric Lippert Jan 01 '10 at 01:20
  • The C#3 type inferer is not the smartest I met. Most functional languages are way better, and also haXe, being a imperative language, has a very strong inferer, which also infers beyond point of initialization. For example in the case of Eric Lippert, the type would depend on what the use is afterwards. If it would be used as some function argument of type int, the var would be inferred int. The compiler just looks every place it is used, what type it is, and based on that, infers the type. If needed to dynamic. – Dykam Jan 02 '10 at 15:24
  • Actually, that is the theorem. The inferer is a little flawed atm. – Dykam Jan 02 '10 at 15:25
  • some things just suck! thanks for pointing out the ? operator, It seems the right place to use var (ie with results from LINQ) I am just a beginner but I somehow manage to hit all the road blocks setup nicely by some design team :) two steps forward, 1 step backward.... :( it really does not scale up as pointed out. Let us know if you manage to find a different coding approach. Thanks. – Marie Apr 27 '11 at 10:26

2 Answers2

8

You could use .Where(...) rather than query syntax:

var participants = email == null
    ? db.Participant.Where(p => p.SequenceNumber == seqNr)
    : db.Participant.Where(p => p.EmailAddress == email);

but personally I simply wouldn't use var here - it doesn't scale beyond 2, but this is a classic "search" pattern. I might use:

IQueryable<Part> query = db.Participant;
if(email != null) query = query.Where(p => p.EmailAddress == email);
if(seqNr != null) query = query.Where(p => p.SequenceNumber == seqNr);
...
// consume query

This allows multiple conditions to be composed (in this case "AND") for a more specific query. You can also do "OR" but it is slightly more complex (unless you use Concat/Union, which is messy).

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
0

This strikes me as a workaround for a database design problem.

I think the more elegant approach would be factoring the code in such a way as to have one method that handles each different program condition.

I.e.:

if (email == null) {
    DoStuffWhenEmailIsNull();
}
else {
    DoStuffWhenEmailIsNotNull();
}
Seth
  • 45,033
  • 10
  • 85
  • 120
  • Except that the "Stuff" is identical in each case, just the means of selecting the result set is different. This approach would lead to either redundant processing code, or just shift the problem to a method used by both of those new methods. – Eric J. Dec 31 '09 at 23:49