views:

372

answers:

6

One of my team has recently come across an interesting glitch in the matrix. If anyone can help explain this it'd be great. It is possibly a complicated to explain, so bear with me.

We are building an ASP.Net application. In it we have a simple "if" statement.

Guid adminId = Guid.Empty;
if (mRoles.Contains("Admin"))
{
    adminId = mUserId;
}

(where mRoles is a List and contains “Admin”)

This works just as expected (i.e adminID is assigned the mUserId). However, when rewritten to use a ternary operator below it doesn't! (adminID is assigned Guid Empty)!

Guid adminId = mRoles.Contains("Admin") ? mUserId : Guid.Empty;

The developer that discovered this is on a 64-bit machine (IIS7/64-bit vista) and if he changes his settings in IIS as follows... Under "Default Application Pool" > "Advanced Settings" check "Enable 32-bit applications." Now both statements work!

We think that this is something to do possibly with the fact that a Guid is a struct rather than a class and that the value is somehow being offset under a 64-bit process.

I suspect the problem is similar to this... http://www.mail-archive.com/[email protected]/msg00164.html Which may explain why the first simple if statement works. (as creating the adminId variable is maybe creating a pointer and the ternary operator is not?)

If anyone could shed any light on this that’d be great. Is it a compatibility bug? or our misunderstanding of combining ternary operators and structs?

Thanks.

UPDATE

Put together a simple application and cannot reproduce it on a completely new project, so must be something else than the GUIDs.

// Works (assigns mUserId to adminId)

Guid adminId = true ? mUserId : Guid.Empty;

// Not working (even though t == true !!!!???)

bool t = (mRoles.Contains("TenantAdmin");
Guid adminId = t ? mUserId : Guid.Empty;

I think we'll be going back to the drawing board on this. Thanks everyone for your help and if we get any further I'll post back here again.

The only thing that maybe wasn't too clear was that mRoles is not a Generic List of Type string. It's a string[] and the Contains() method is LINQs extension method if that makes any difference, but can't see why :-?

UPDATE 2

We've looked at the IL and it is correct (and now works intermittently!) What we've found is that when the Default App pool loads more applications it starts to fail again. The only other thing we can think of is that some of these other applications may contain some unmanaged code which is somehow interfering with our application, could this be possible?

A: 

Maybe it will help to specifically tell the assignment operator that the return from the ternary operator is Guid?

Guid adminId = (Guid)(mRoles.Contains("Admin") ? mUserId : Guid.Empty);

Just a wild guess...

awe
Nope. still not working.
ChrisV
Similar wild guess -- could this be order of evaluation? Try putting parens around the ternary statement to ensure that you're not parsing the assignment as the conditional.
mpez0
A: 

just wondering what type the 64bit machine thinks mUserId is? Presumably not a Guid.

Massif
Definitly a System.Guid :-(
ChrisV
You'd get a compiler error about not being able to determine the return type if mUserId wasn't a guid.
Mark
A: 

I'm not sure, but I think when using a tenary operation, both brances have to be executed, however with GUID, this may cause two GUIDs to be evaluated some how.

Darknight
+1  A: 

Please try parenthesis around your ternary operator, if you haven't done so already.

We had a similar problem in which code like yours:

Guid adminId = t ? mUserId : Guid.Empty;

was compiled in the wrong order:

(Guid adminId = t) ? mUserId : Guid.Empty;

Adding parenthesis to specify the order fixed it:

Guid adminId = (t ? mUserId : Guid.Empty);

I figured out what it was doing by looking at the compiled code with .NET Reflector.

Paul Williams
A: 

Have you tried the following:

Guid adminId = mRoles.Contains("Admin") ? (Guid)mUserId : Guid.Empty;

Just curious if, for whatever reason, mUserId is internally recognized as a different type under a 64bit operating system, and if explicitly casting would help. The following might also be an option:

Guid adminId = mRoles.Contains("Admin") ? new Guid(mUserId.ToByteArray()) : Guid.Empty;
jrista
A: 

This appears to be a bug in IIS and a chunk of unmanaged code in another application runnning in the same applcation pool. We have worked around it for now and will raise it with Microsoft via our partnership. When it gets resolved I'll post back here to let you know.

Thanks everyone for all your help.

ChrisV