هل هناك حل بديل للتحميل الزائد لمشغل المهمة في C#؟

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

  •  08-07-2019
  •  | 
  •  

سؤال

على عكس C++، في C# لا يمكنك زيادة التحميل على عامل المهمة.

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

هنا مثال:

Number a = new Number(55); 
Number b = a; //I want to copy the value, not the reference

هل هناك حل لهذه المشكلة؟

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

المحلول

لا يزال من غير الواضح بالنسبة لي أنك بحاجة إلى هذا حقًا.أيضاً:

  • يجب أن يكون نوع الرقم الخاص بك عبارة عن بنية (وهو أمر محتمل - الأرقام هي المثال الأكثر شيوعًا للبنيات).لاحظ أن جميع الأنواع التي تريد أن يتصرف بها نوعك مثل (int، وdecimal، وما إلى ذلك) هي بنيات.

أو:

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

نصائح أخرى

ويمكنك استخدام الكلمة "ضمني" لخلق الزائد لهذه المهمة:

وافترض أن لديك نوع مثل فو، الذي تشعرين به هو CONVERTABLE ضمنا من السلسلة. أن تكتب أسلوب ثابت التالية في الصف فو الخاص بك:

public static implicit operator Foo(string normalString)
{
    //write your code here to go from string to Foo and return the new Foo.
}

وبعد الانتهاء من ذلك، يمكنك بعد ذلك استخدام التالية في التعليمات البرمجية:

Foo x = "whatever";

لن تتمكن من حل هذه المشكلة باستخدام مظهر C++، نظرًا لأن a = b;له دلالات أخرى في C++ مقارنة بـ C#.في C#، أ = ب؛يشير إلى نفس الكائن مثل b.في C++، a = b يغير محتوى a.كلاهما له صعودا وهبوطا.انها مثلك تفعل

MyType * a = new MyType();
MyType * b = new MyType(); 
a = b; /* only exchange pointers. will not change any content */

في C++ (سيفقد المرجع إلى الكائن الأول، ويؤدي إلى حدوث تسرب للذاكرة.ولكن دعونا نتجاهل ذلك هنا).لا يمكنك زيادة تحميل عامل التعيين في C++ لذلك أيضًا.

الحل سهل:

MyType a = new MyType();
MyType b = new MyType();

// instead of a = b
a.Assign(b);

تنصل:أنا لست مطور C#

يمكنك إنشاء خاصية للكتابة فقط مثل هذا.ثم افعل a.Self = b;فوق.

public MyType Self {
    set {
        /* copy content of value to this */
        this.Assign(value);
    }
}

الآن، هذا هو لا جيد.لأنه ينتهك مبدأ المفاجأة الأقل (POLS).لا يتوقع المرء أن يتغير إذا فعل المرء a.Self = b;

وبدلا من تقديم نسخة من البيانات عند تمرير المرجعية التي يمكن أن تجعل الطبقة غير قابل للتغيير. عندما الطبقة هي ثابتة وجود إشارات متعددة لأنها ليست مشكلة لأنه لا يمكن تغييرها.

والعمليات التي تغري البيانات ستكون بالطبع يعود الحالات الجديدة.

واقترح أحد آخر في وقت سابق هذا:

<اقتباس فقرة>   

والعام المشغل الضمني ثابت فو (سلسلة normalString) {}

وحاولت هذه الطريقة ... ولكن العمل على انجاحه كنت بحاجة إلى هذا:

والعام المشغل الضمني ثابت فو (فو الأصلي) {}

ووسوف مترجم تدع لديك وظيفة التحويل الضمني من نوع بك على وجه الدقة، ولا من أي نوع قاعدة نفسك. هذا الأمر يبدو معقولا تماما لأنه سيكون وسيلة مستتر من تجاوز عامل التعيين، الذي C # لا تريد السماح.

وهنا هو الحل الذي عملت لنفسي:

public class MyTestClass
{
   private int a;
   private string str;

   public MyTestClass()
   {
      a = 0;
      str = null;
   }

   public MyTestClass(int a, string str)
   {
      this.a = a;
      this.str = str;
   }

   public MyTestClass Clone
   {
      get
      {
         return new MyTestClass(this.a, this.str);
      }
   }
}

وفي مكان آخر في التعليمات البرمجية:

MyTestClass test1 = new MyTestClass(5, "Cat");
MyTestClass test2 = test1.Clone;

وربما ما كنت تبحث عن لا يمكن حلها باستخدام C # يمكنهم الدخول.

http://msdn.microsoft.com /en-us/library/aa287786(v=vs.71).aspx

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