.NET Reflector가 .NET Framework에서 수행되었음을 보여 주면 속성이나 인덱서를 Ref 매개 변수로 전달할 수없는 이유는 무엇입니까?

StackOverflow https://stackoverflow.com/questions/1810785

  •  05-07-2019
  •  | 
  •  

문제

좋아, 나는 .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...
}

이 코드 라인은 .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
}

그것이하고있는 모든 것이 의미가 있습니다 - 종이에 ... 그래서 나는 비슷한 것을 사용하고 싶은 곳을위한 빠른 작은 프로토 타입을 두드리게됩니다.

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.
    }
}

이 코드는 컴파일되지 않습니다 - 오류는 다음과 같이 표시됩니다.

"A property or indexer may not be passed as an out or ref parameter"

충분히 공정 ...하지만 왜 내 코드가 .NET Framework 코드 기반에있는 것처럼 보이는 일을 할 수없는 이유는 무엇입니까? .NET Reflector가 DLL을 해석하는 방식에 오류입니까, 아니면 코드를 해석하는 방식의 오류입니까?

도움이 되었습니까?

해결책

나는 그것이 반사판의 나쁜 해석이라고 생각합니다. 실제로 다음과 같이 코드를 작성하는 경우 :

static void Main(string[] args)
{
    DummyClass x = new DummyClass();
    string username = x.ClassName;
    DoSomething(ref username);
}

릴리스 모드로 컴파일하면 반사기 에서이 사실이 표시됩니다.

static void Main(string[] args)
{
    DummyClass x = new DummyClass();
    DoSomething(ref x.ClassName);
}

C# 컴파일러는 C# 코드를 생성하는 것이 아니라 IL을 생성하므로 반사기에서 보는 것이 항상 현실이 아닙니다. 따라서 후드 아래에서 무슨 일이 일어나고 있는지 명확하게 이해하려면 컴파일러가 생성 한 실제 코드를 볼 수 있습니다.

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)

로컬 변수가 사용 된 것은 분명합니다.

다른 팁

반사기 버그입니다. 실제로 부동산을 참조하여 전달하는 것은 아닙니다.

다음은 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)
    {
    }
}

반사판은이 코드를 보여줍니다 Foo:

private static void Foo(Person p)
{
    Bar(ref p.Name);
}

이 유효하지 않은 C#일뿐 만 아니라 오해의 소지가 있습니다. x 이내에 Bar 어떻게 든 수정할 것입니다 p.Name - 원래 C# 코드를 볼 때는 그렇지 않습니다.

원래 샘플에서 UserName 읽기 전용 속성입니다!

기능을 전달하기 전에 속성 값을 변수로 설정하십시오.

string myClassName = x.ClassName
DoSomething(ref myClassName);

가장 우아한 솔루션은 아니지만 올바른 방향을 가리 킵니다. Yuriy가 위의 의견에서 말했듯이, 아마도 당신은 당신이 재산을 명시 적으로 선언하지 않았다는 사실과 관련이있을 것입니다.

변수를 Ref 또는 Out로 전달하면 호출이 원래 위치에있는 메모리를 실제로 가리 킵니다. 따라서 부동산을 참조로 통과 할 수 있다면 클래스 멤버를 일관성있게 만들고 있음을 의미합니다. 이것이이 문제의 이유입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top