2

At first I had some code like this:

WindowsIdentity otherIdentity = // got that from somewhere else
WindowsImpersonationContext context = otherIdentity.Impersonate();
Ldap.DoStuff();
context.Undo();
context.Dispose();

Knowing that WindowsImpersonationContext implements IDisposable and Dispose() also calls Undo(), I think I should be using using instead:

using (var context = otherIdentity.Impersonate())
{
    // Run as other user
    Ldap.DoStuff();
}

Now, ReSharper correctly notices that I am not using context and suggests to remove the assignment. Does this also work? To what code does it expand at compile time?

using (otherIdentity.Impersonate())
{
    Ldap.DoStuff();
}
djk
  • 943
  • 2
  • 9
  • 27
  • 3
    To test whether this works, build and run. – adv12 Jan 19 '17 at 16:39
  • @adv12: It will 'work' either way regardless if the object is disposed or not, and the garbage collector disposes it at some point anyway. But even if `using` is disposing it, I wonder how. Does the statement keep an unnamed reference of the expression result? Of all expression results? The documentation never mentions that... – djk Jan 19 '17 at 16:45
  • 2
    I would consider using `try-finally` instead of `using` here. The revocation of impersonation is important and should be emphasized in the code, not hidden. – Eric Lippert Jan 19 '17 at 17:08
  • 3
    Also, as I always remind people who are doing impersonation: if the `DoStuff` can throw then any *exception filters* in the caller will run *before* the `finally` or `using` calls `Undo` or `Dispose`. That means that the code in the filter will be run in a context that impersonates the other user, which might not be what you want. The safest pattern is to use `try-catch-finally` where both the catch and finally do the `Undo`. So that's another reason to not use `using`. – Eric Lippert Jan 19 '17 at 17:27

1 Answers1

4

Yes, you can omit the variable in a using statement, and the compiler will automatically introduce a hidden variable as if you had written

using (var temp = otherIdentity.Impersonate())
{
    Ldap.DoStuff();
}

except that you can't access temp in the body of the using statement.

Curiously, this syntax doesn't seem to be documented in MSDN Library. Instead, refer to the C# specification:

A using statement of the form

using (ResourceType resource = expression) statement

corresponds to one of three possible expansions.

[...]

A using statement of the form

using (expression) statement

has the same three possible expansions. In this case ResourceType is implicitly the compile-time type of the expression, if it has one. Otherwise the interface IDisposable itself is used as the ResourceType. The resource variable is inaccessible in, and invisible to, the embedded statement.

Michael Liu
  • 52,147
  • 13
  • 117
  • 150