Ben*_*ter 12 .net c# .net-reflector
好的,我将从.NET反射器剪切和粘贴以演示我正在尝试做的事情:
public override void UpdateUser(MembershipUser user)
{
//A bunch of irrelevant code...
SecUtility.CheckParameter(ref user.UserName, true, true, true, 0x100, "UserName");
//More irrelevant code...
}
Run Code Online (Sandbox Code Playgroud)
这行代码来自.NET Framework中的System.Web.Security.SqlMembershipProvider.UpdateUser(System.Web.dll v2.0.50727).
SecUtility.CheckParameter需要一个引用值作为第一个参数,它们将传入的用户属性作为参数传递给它.
CheckParameter代码的定义是:
internal static void CheckParameter(ref string param, bool checkForNull, bool checkIfEmpty, bool checkForCommas, int maxSize, string paramName)
{
//Code omitted for brevity
}
Run Code Online (Sandbox Code Playgroud)
它所做的一切都很有意义 - 在纸面上...所以我在某个地方敲了一个快速的小原型,我想用类似的东西:
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.
}
}
Run Code Online (Sandbox Code Playgroud)
此代码将无法编译 - 错误显示为:
"A property or indexer may not be passed as an out or ref parameter"
Run Code Online (Sandbox Code Playgroud)
很公平......但为什么我的代码不允许我做一些似乎在.NET Framework代码库中的东西?这是.NET Reflector解释DLL的方式的错误,或者这是我解释其代码的方式的错误?
Dar*_*rov 15
我认为这是Reflector的一些不好的解释.实际上,如果你编写这样的代码:
static void Main(string[] args)
{
DummyClass x = new DummyClass();
string username = x.ClassName;
DoSomething(ref username);
}
Run Code Online (Sandbox Code Playgroud)
并在发布模式下编译它,您将在Reflector中看到:
static void Main(string[] args)
{
DummyClass x = new DummyClass();
DoSomething(ref x.ClassName);
}
Run Code Online (Sandbox Code Playgroud)
请记住,C#编译器不会生成C#代码,而是IL,因此您在Reflector中看到的并不总是现实.因此,为了清楚地了解底层的内容,您可以查看编译器生成的实际代码:
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)
Run Code Online (Sandbox Code Playgroud)
很明显,使用了局部变量.
这是一个反射器错误.它并没有真正通过引用传递属性.
这里有一些C#代码可以重现它.
using System;
class Person
{
public string Name { get; set; }
}
class Test
{
static void Main(){} // Just make it easier to compile
static void Foo(Person p)
{
string tmp = p.Name;
Bar(ref tmp);
}
static void Bar(ref string x)
{
}
}
Run Code Online (Sandbox Code Playgroud)
Reflector显示以下代码Foo:
private static void Foo(Person p)
{
Bar(ref p.Name);
}
Run Code Online (Sandbox Code Playgroud)
这不仅是无效的C#,而且它具有误导性 - 它会暗示对x内部进行的更改Bar会以某种方式进行修改p.Name- 在您查看原始C#代码时并非如此.
在您的原始样本中,它UserName只是一个只读属性的意义!
| 归档时间: |
|
| 查看次数: |
12799 次 |
| 最近记录: |