Okay, I will cut and paste from .NET reflector to demonstrate what I'm trying to do:
public override void UpdateUser(MembershipUser user)
{
//A bunch of irrelevant code...
SecUtility.CheckParameter(ref user.UserName, true, true, true, 0x100, "UserName");
//More irrelevant code...
}
This line of code comes right out of System.Web.Security.SqlMembershipProvider.UpdateUser (System.Web.dll v2.0.50727) in the .NET Framework.
The SecUtility.CheckParameter requires a reference value as the first parameter, to which they're passing a property of the user passed in as the argument.
The definition of the CheckParameter code is:
internal static void CheckParameter(ref string param, bool checkForNull, bool checkIfEmpty, bool checkForCommas, int maxSize, string paramName)
{
//Code omitted for brevity
}
Everything it's doing makes sense - on paper... so I knock up a quick little prototype for somewhere I'd like to use something similar:
public class DummyClass
{
public string ClassName{ get; set; }
}
public class Program
{
private static DoSomething(ref string value)
{
//Do something with the value passed in
}
public static Main(string[] args)
{
DummyClass x = new DummyClass() { ClassName = "Hello World" };
DoSomething(ref x.ClassName); //This line has a red squiggly underline
//under x.ClassName indicating the
//error provided below.
}
}
This code won't compile - the error shows as:
"A property or indexer may not be passed as an out or ref parameter"
Fair enough... but why won't my code allow me to do something that appears to be in the .NET Framework code base? Is this an error with the way .NET Reflector is interpreting the DLL or is this an error with the way I'm interpreting their code?
I think it is some bad interpretation from Reflector. Actually if you write your code like this:
static void Main(string[] args)
{
DummyClass x = new DummyClass();
string username = x.ClassName;
DoSomething(ref username);
}
and compile it in Release mode you will see this in Reflector:
static void Main(string[] args)
{
DummyClass x = new DummyClass();
DoSomething(ref x.ClassName);
}
Remember that the C# compiler is not producing C# code but IL so what you see in Reflector is not always the reality. So to clearly understand what is going on under the hood you may look at the real code produced by the compiler:
L_000f: callvirt instance string System.Web.Security.MembershipUser::get_UserName()
L_0014: stloc.0
L_0015: ldloca.s str
L_0017: ldc.i4.1
L_0018: ldc.i4.1
L_0019: ldc.i4.1
L_001a: ldc.i4 0x100
L_001f: ldstr "UserName"
L_0024: call void System.Web.Util.SecUtility::CheckParameter(string&, bool, bool, bool, int32, string)
It is clear that a local variable is used.