سؤال

لقد حددت البنية التالية:

public struct Call
{
    public SourceFile caller;
    public SourceFile callee;

    public Call(SourceFile caller, SourceFile callee)
    {
        this.caller = caller;
        this.callee = callee;
    }
}

في وقت لاحق ، أقوم بتعيينها إلى خاصية علامة كائن آخر:

line.Tag = new Call(sf1, sf2);

ولكن عندما أحاول استرداد خاصية العلامة مثل ذلك ،

Call call = line.Tag as Call;

يعطي Visual Studio خطأ الترجمة التالي:

يجب استخدام المشغل في نوع مرجعي أو نوع لاغ

ما معنى ذلك؟ وكيف يمكنني حلها؟

هل كانت مفيدة؟

المحلول

الهيكل هو نوع قيمة ، لذلك لا يمكن استخدامه مع as المشغل أو العامل. ال as يجب أن يكون المشغل قادرًا على تعيين قيمة فارغة إذا فشل فريق العمل. هذا ممكن فقط مع نوع مرجع أو نوع قيمة لاغية.

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

لمزيد من المعلومات حول أنواع القيمة مقابل الأنواع المرجعية ، هذه هو مقال لائق. أيضا ، إلقاء نظرة على MSDN:

نصائح أخرى

بعض الإجابات الحالية ليست تمامًا حق. لا يمكنك استخدام غير قابلة للفرق الأنواع مع as, ، لأن نتيجة as هي القيمة الخالية من النوع إذا كان المعامل الأول ليس بالفعل من النوع المناسب.

ولكن هل تستطيع استعمال as مع أنواع القيمة ... إذا كانت قابلة للإلغاء:

int a = 10;
object o = a;

int? x = o as int?; // x is a Nullable<int> with value 10
long? y = o as long?; // y is a Nullable<long> with the null value

وانت ايضا يستطع استعمال:

Call? call = line.Tag as Call?;

ثم يمكنك استخدامه على النحو التالي:

if (call != null)
{
    // Do stuff with call.Value
}

تحذيرتين على الرغم من:

  • في تجربتي هذا أبطأ من مجرد استخدام is تليها طاقم
  • يجب عليك إعادة النظر بجدية Call يكتب:
    • إنها تعرض المجالات العامة ، والتي تعتبر غلافًا ضعيفًا بشكل عام
    • إنه نوع قيمة قابل للتغيير ، وهو بالتأكيد خطأ

أود أن أقترح بشدة أن تجعله فصلًا بدلاً من ذلك - عند هذه النقطة تختفي هذه المشكلة على أي حال.

فكرة أخرى: إذا كان يجب على العلامة دائماً كن Call, ، ثم من الأفضل إلقاءها:

Call call = (Call) line.Tag;

وبهذه الطريقة ، إذا كانت البيانات لا تتطابق مع توقعاتك (أي هناك بعض الأخطاء مثل Tag ليس أ Call) ثم يمكنك معرفة ذلك في وقت مبكر ، بدلاً من ذلك بعد أن تقوم ببعض الأعمال الأخرى. لاحظ أن هذا الممثل سوف يتصرف بشكل مختلف اعتمادًا على ما إذا كان Call هو بنية أو فئة ، إذا Tag IS NULL - يمكنك إلقاء قيمة فارغة لمتغير من نوع مرجع (أو نوع قيمة لاغية) ، ولكن ليس لنوع قيمة غير قابل للفرق.

من C# spec

§7.10.11 يتم استخدام المشغل AS لتحويل قيمة بشكل صريح إلى نوع مرجع أو نوع لاغية. على عكس التعبير المصبوب (الفقرة 7.7.6) ، فإن المشغل AS لا يلقي أبدًا استثناء. بدلاً من ذلك ، إذا كان التحويل المشار إليه غير ممكن ، فالقيمة الناتجة باطل.

يمكن أن تكون المراجع والأنواع الباطئة لاغية. الخطوط هي أنواع القيمة بحيث لا يمكن أن تكون فارغة.

Call? call = line.Tag as Call?;

إنه قيود على C#. إذا كان النوع هو نوع مرجعي ، فإذا فشل الممثلون ، فسيعود ببساطة "NULL" ، ولكن نظرًا لأنه نوع قيمة ، فلا يعرف ما الذي يعود عند فشل فريق الممثلين.

يجب أن تحل محل استخدامك لـ اثنين: "IS" و "As"

if (line.Tag is Call) {
  call = (Call)line.Tag;
} else {
  // Do whatever you would do if as returned null.
}

ما هو المعنى - كما هو مذكور ، الهياكل هي أنواع القيمة.

كيف يمكنني حلها - تغييرها

Call call = line.Tag;
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top