لماذا لا أستطيع تمرير خاصية أو مفهرس كمعلمة المرجع عندما يظهر صافي العاكس أن يتم ذلك في .NET Framework؟

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

وهذا سطر من التعليمات البرمجية يأتي الحق في الخروج من System.Web.Security.SqlMembershipProvider.UpdateUser (SYSTEM.WEB.DLL V2.0.50727) في .NET Framework.

وو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 العاكس هو تفسير 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);

وانها ليست الحل الأكثر أناقة، ولكن يجب أن نشير لكم في الاتجاه الصحيح. كما قال يوري في تعليقه أعلاه، على الأرجح أن تفعل شيئا مع حقيقة أنك لا تعلن صراحة الحصول على وتعيين الخاصية.

عند تمرير متغير باعتباره المرجع أو خارج، والدعوة ويشير في الواقع إلى الذاكرة حيث يقع أصلا. حتى إذا كان مسموحا لك لتمرير الملكية كمرجع، فهذا يعني أنك اتخاذ عضو فئة غير متناسقة. وهذا هو السبب وراء هذه المشكلة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top