c# - معنى - ما هو الفرق بين الحقل والممتلكات؟




معنى كلمة عنوان بالانجليزي (20)

الاختلافات - الاستخدامات (متى ولماذا)

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

الخاصية هي عضو يوفر آلية مرنة لقراءة أو كتابة أو حساب قيمة حقل خاص. يمكن استخدام الخصائص كما لو كانت أعضاء بيانات عامة ، ولكنها في الواقع طرق خاصة تسمى accessors . وهذا يتيح الوصول إلى البيانات بسهولة ويساعد على تعزيز سلامة ومرونة الأساليب . تعمل الخصائص على تمكين الطبقة من كشف طريقة عامة للحصول على القيم وإعدادها ، مع إخفاء رمز التنفيذ أو التحقق. يتم استخدام get get property accessor لإرجاع قيمة الخاصية ، ويتم استخدام أداة access Set لتعيين قيمة جديدة.

في C # ، ما الذي يجعل الحقل مختلفًا عن خاصية ، ومتى يجب استخدام حقل بدلاً من خاصية؟


(يجب أن يكون هذا بالفعل تعليقًا ، ولكن لا يمكنني نشر تعليق ، لذا يرجى العذر إذا لم يكن مناسبًا كمشاركة).

عملت ذات مرة في مكان حيث كانت الممارسة الموصى بها هي استخدام الحقول العامة بدلاً من الخصائص عندما كان عيب الخاصية المكافئة مجرد الوصول إلى حقل ، كما في:

get { return _afield; }
set { _afield = value; }

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

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


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


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


الخصائص هي نوع خاص من أعضاء الصف ، في خصائص نستخدم طريقة محددة مسبقا أو طريقة get.They استخدام accessors من خلالها يمكننا قراءة أو كتابة أو تغيير قيم الحقول الخاصة.

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

لماذا نستخدم الخصائص؟

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

لفهم هذا بشكل واضح مع مثال ، دعنا نأخذ طالبًا دراسيًا لديه هوية أو علامة أو اسم. الآن في هذا المثال بعض المشاكل مع المجال العام

  • يجب أن لا يكون معرف -ve.
  • لا يمكن تعيين الاسم على قيمة خالية
  • يجب قراءة علامة المرور فقط.
  • إذا كان اسم الطالب مفقودًا ، فيجب الرجوع إلى "الاسم".

لإزالة هذه المشكلة ، نستخدم أسلوب Get and set.

// A simple example
public class student
{
    public int ID;
    public int passmark;
    public string name;
}

public class Program
{
    public static void Main(string[] args)
    {
       student s1 = new student();
       s1.ID = -101; // here ID can't be -ve
       s1.Name = null ; // here Name can't be null
    }
}

الآن نحن نأخذ مثالا على الحصول على طريقة وضبطها

public class student
{
    private int _ID;
    private int _passmark;
    private string_name ;
    // for id property
    public void SetID(int ID)
    {
        if(ID<=0)
        {
            throw new exception("student ID should be greater then 0");
        }
        this._ID = ID;
    }
    public int getID()
    {
        return_ID;
    }
}
public class programme
{
    public static void main()
    {
        student s1 = new student ();
        s1.SetID(101);
    }
    // Like this we also can use for Name property
    public void SetName(string Name)
    {
        if(string.IsNullOrEmpty(Name))
        {
            throw new exeception("name can not be null");
        }
        this._Name = Name;
    }
    public string GetName()
    {
        if( string.IsNullOrEmpty(This.Name))
        {
            return "No Name";
        }
        else
        {
            return this._name;
        }
    }
        // Like this we also can use for Passmark property
    public int Getpassmark()
    {
        return this._passmark;
    }
}

السؤال الثاني هنا ، "متى يجب استخدام حقل بدلاً من خاصية؟" ، تم التطرق إليه بإيجاز فقط في هذه الإجابة الأخرى ، وهذا النوع أيضًا ، ولكن ليس الكثير من التفاصيل.

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

ولكن هناك ميزة واحدة أن الحقول لها خصائص ، وهذه هي قدرتها على استخدامها كمعلمات "ref" / "out". افترض أن لديك طريقة بالتوقيع التالي:

public void TransformPoint(ref double x, ref double y);

وافترض أنك تريد استخدام هذه الطريقة لتحويل صفيف تم إنشاؤه على النحو التالي:

System.Windows.Point[] points = new Point[1000000];
Initialize(points);

وهنا أعتقد أن أسرع طريقة للقيام بذلك ، منذ X و Y هي خصائص:

for (int i = 0; i < points.Length; i++)
{
    double x = points[i].X;
    double y = points[i].Y;
    TransformPoint(ref x, ref y);
    points[i].X = x;
    points[i].Y = y;
}

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

internal struct MyPoint
{
    internal double X;
    internal double Y;
}

// ...

MyPoint[] points = new MyPoint[1000000];
Initialize(points);

// ...

for (int i = 0; i < points.Length; i++)
{
    TransformPoint(ref points[i].X, ref points[i].Y);
}

عند إجراء بعض measurements بنفسي ، يستغرق الإصدار مع الحقول حوالي 61٪ من الوقت كإصدار يحتوي على خصائص (.NET 4.6 ، Windows 7 ، x64 ، وضع التحرير ، دون مصحح أخطاء مرفقة). وكلما ازدادت تكلفة طريقة TransformPoint كلما كان الفرق أقل. لتكرار هذا بنفسك ، قم بتشغيل مع السطر الأول مع التعليق عليها ومع عدم التعليق عليها.

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

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


بما أن العديد منها قد أوضح بإيجابيات وعيوب تقنية من Properties Field ، فقد حان الوقت للوصول إلى أمثلة في الوقت الحقيقي.

1. خصائص تسمح لك بتعيين مستوى الوصول للقراءة فقط

خذ بعين الاعتبار حالة dataTable.Rows.Count و dataTable.Columns[i].Caption . يأتون من فئة DataTable وكلاهما عام بالنسبة لنا. الاختلاف في مستوى الوصول إليها هو أننا لا نستطيع تعيين القيمة إلى dataTable.Rows.Count ولكن يمكننا القراءة والكتابة إلى dataTable.Columns[i].Caption . هل هذا ممكن من خلال Field ؟ لا!!! ويمكن القيام بذلك مع Properties فقط.

public class DataTable
{
    public class Rows
    {       
       private string _count;        

       // This Count will be accessable to us but have used only "get" ie, readonly
       public int Count
       {
           get
           {
              return _count;
           }       
       }
    } 

    public class Columns
    {
        private string _caption;        

        // Used both "get" and "set" ie, readable and writable
        public string Caption
        {
           get
           {
              return _caption;
           }
           set
           {
              _caption = value;
           }
       }       
    } 
}

2. خصائص في PropertyGrid

ربما تكون قد عملت مع Button في Visual Studio. تظهر خصائصه في PropertyGrid مثل Text ، Name etc. عندما نقوم بسحب وإفلات زر ، وعندما نضغط على الخصائص ، فإنه سيعثر تلقائيًا على Button الفلاتر والفلاتر Properties ويعرض ذلك في PropertyGrid (حيث لن يظهر PropertyGrid Field على الرغم من أنها عامة).

public class Button
{
    private string _text;        
    private string _name;
    private string _someProperty;

    public string Text
    {
        get
        {
           return _text;
        }
        set
        {
           _text = value;
        }
   } 

   public string Name
   {
        get
        {
           return _name;
        }
        set
        {
           _name = value;
        }
   } 

   [Browsable(false)]
   public string SomeProperty
   {
        get
        {
           return _someProperty;
        }
        set
        {
           _someProperty= value;
        }
   } 

في PropertyGrid ، سيتم عرض خصائص Name Text ، ولكن ليس SomeProperty . لماذا ا؟؟؟ لأنه يمكن خصائص قبول Attributes . لا تظهر في حالة [Browsable(false)] false.

3. يمكن تنفيذ العبارات داخل خصائص

public class Rows
{       
    private string _count;        


    public int Count
    {
        get
        {
           return CalculateNoOfRows();
        }  
    } 

    public int CalculateNoOfRows()
    {
         // Calculation here and finally set the value to _count
         return _count;
    }
}

4. يمكن استخدام الخصائص فقط في ربط المصدر

يساعدنا " ملزمة المصدر" على تقليل عدد أسطر التعليمات البرمجية. Fields غير مقبولة بواسطة BindingSource . يجب علينا استخدام Properties لذلك.

5. وضع التصحيح

ضع في الاعتبار أننا نستخدم Field للاحتفاظ بقيمة. في مرحلة ما ، نحتاج إلى تصحيح الأخطاء والتحقق من المكان الذي تحصل فيه القيمة على قيمة خالية لهذا الحقل. سيكون من الصعب القيام بذلك عندما يكون عدد أسطر التعليمات البرمجية أكثر من 1000. في مثل هذه الحالات ، يمكننا استخدام Property ويمكن ضبط وضع التصحيح داخل Property .

   public string Name
   {
        // Can set debug mode inside get or set
        get
        {
           return _name;
        }
        set
        {
           _name = value;
        }
   }

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

إذا قمت بكتابة مكتبة فئة مصممة للاستهلاك الواسع (مثل .NET Framework ، والذي يستخدمه الملايين من الأشخاص) ، فقد يكون ذلك مشكلة. ومع ذلك ، إذا كنت تكتب فئة مستخدمة داخليًا داخل قاعدة رمز صغيرة (على سبيل المثال <= 50 كلاً من الخطوط) ، فهي في الحقيقة ليست صفقة كبيرة ، لأنه لن يتأثر أي شخص بشكل سلبي بالتغييرات التي أجريتها. في هذه الحالة ، ينحصر الأمر في تفضيل شخصي.


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

قد تعمل الخصائص لفترة طويلة جدًا ، ولها تأثيرات جانبية ، وربما تؤدي إلى استثناءات. الحقول سريعة ، بدون أي آثار جانبية ، ولن تضع استثناءات أبدًا. بسبب الآثار الجانبية ، قد تقوم الخاصية بإرجاع قيمة مختلفة لكل مكالمة (كما قد يكون الحال في DateTime.Now ، أي أن DateTime.Now ليس دائمًا يساوي DateTime.Now). الحقول دائما بإرجاع نفس القيمة.

يمكن استخدام الحقول لمعلمات out / ref ، وقد لا تستخدم الخصائص. تدعم الخصائص منطقًا إضافيًا - يمكن استخدام هذا لتنفيذ التحميل البطيء ضمن أشياء أخرى.

تدعم الخصائص مستوى التجريد بتغليف ما يعنيه الحصول على القيمة.

استخدم الخصائص في معظم الحالات / كلها ، ولكن حاول تجنب الآثار الجانبية.


تصميمي للحقل هو أن الحقل يحتاج إلى تعديله فقط بواسطة الأصل ، ومن ثم الفئة. نتيجة المتغير يصبح خاصا ، ثم أن تكون قادرة على إعطاء الحق في قراءة الطبقات / الأساليب خارج أذهب من خلال نظام الملكية مع فقط الحصول على. يتم استرداد الحقل من قبل الملكية والقراءة فقط! If you want to modify it you have to go through methods (for example the constructor) and I find that thanks to this way of making you secure, we have better control over our code because we "flange". One could very well always put everything in public so every possible case, the notion of variables / methods / classes etc ... in my opinion is just an aid to the development, maintenance of the code. For example, if a person resumes a code with public fields, he can do anything and therefore things "illogical" in relation to the objective, the logic of why the code was written. It's my point of view.

When i use a classic model private field / public readonly properties,for 10 privates fields i should write 10 publics properties! The code can be really big faster. I discover the private setter and now i only use public properties with a private setter. The setter create in background a private field.

That why my old classic programming style was:

public class MyClass
{
 private int _id;
 public int ID { get { return _id; } }
 public MyClass(int id)
 {
  _id = id;
 }
}

My new programming style:

public class MyClass
{
 public int ID { get; private set; }
 public MyClass(int id)
 {
  ID = id;
 }
}

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


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

public class MyClass
{
    // this is a field.  It is private to your class and stores the actual data.
    private string _myField;

    // this is a property. When accessed it uses the underlying field,
    // but only exposes the contract, which will not be affected by the underlying field
    public string MyProperty
    {
        get
        {
            return _myField;
        }
        set
        {
            _myField = value;
        }
    }

    // This is an AutoProperty (C# 3.0 and higher) - which is a shorthand syntax
    // used to generate a private field for you
    public int AnotherProperty{get;set;} 
}

يشيرKent إلى أن الخصائص غير مطلوبة لتغليف الحقول ، أو القيام بحساب في حقول أخرى ، أو تقديم أغراض أخرى.

يشيرGSS أنه يمكنك أيضا القيام بالمنطق الآخر ، مثل التحقق من الصحة ، عند الوصول إلى خاصية ، ميزة أخرى مفيدة.


عندما تريد أن يتم الوصول إلى متغيرك الخاص (حقل) إلى كائن من صفك من فصول أخرى ، فإنك تحتاج إلى إنشاء خصائص لتلك المتغيرات.

على سبيل المثال ، إذا كان لدي متغيرات تسمى "id" و "name" وهي خاصة ولكن قد يكون هناك موقف حيث يكون هذا المتغير مطلوبًا لعملية القراءة / الكتابة خارج الفصل. في هذه الحالة ، يمكن أن تساعد الخاصية في الحصول على هذا المتغير للقراءة / الكتابة اعتمادًا على get / set المعرّف للعقار. خاصية يمكن أن يكون للقراءة فقط / writeonly / readwrite على حد سواء.

هنا هو التجريبي

class Employee
{
    // Private Fields for Employee
    private int id;
    private string name;

    //Property for id variable/field
    public int EmployeeId
    {
       get
       {
          return id;
       }
       set
       {
          id = value;
       }
    }

    //Property for name variable/field
    public string EmployeeName
    {
       get
       {
          return name;
       }
       set
       {
          name = value;
       }
   }
}

class MyMain
{
    public static void Main(string [] args)
    {
       Employee aEmployee = new Employee();
       aEmployee.EmployeeId = 101;
       aEmployee.EmployeeName = "Sundaran S";
    }
}

عندما يكون لديك فصل "سيارة". الخصائص هي اللون والشكل ..

حيث أن الحقول هي متغيرات محددة في نطاق الفئة.


كما تسمح لك الخصائص باستخدام المنطق عند تحديد القيم.

لذلك يمكنك القول أنك تريد فقط تعيين قيمة لحقل عدد صحيح ، إذا كانت القيمة أكبر من x ، وإلا قم بطرح استثناء.

ميزة مفيدة حقا.


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


يتم تعيين الحقول الخاصة تقليديا عن طريق أساليب getter و setter. من أجل أقل رمز يمكنك استخدام خصائص لتعيين الحقول بدلاً من ذلك.


Additional info: By default, get and set accessors are as accessible as the property itself. You can control/restrict accessor accessibility individually (for get and set) by applying more restrictive access modifiers on them.

مثال:

public string Name
{
    get
    {
        return name;
    }
    protected set
    {
        name = value;
    }
}

Here get is still publicly accessed (as the property is public), but set is protected (a more restricted access specifier).


The vast majority of cases it's going to be a property name that you access as opposed to a variable name ( field ) The reason for that is it's considered good practice in .NET and in C# in particular to protect every piece of data within a class, whether it's an instance variable or a static variable (class variable) because it's associated with a class.

Protect all of those variables with corresponding properties which allow you to define, set and get accessors and do things like validation when you're manipulating those pieces of data.

But in other cases like Math class (System namespace), there are a couple of static properties that are built into the class. one of which is the math constant PI

على سبيل المثال. Math.PI

and because PI is a piece of data that is well-defined, we don't need to have multiple copies of PI, it always going to be the same value. So static variables are sometimes used to share data amongst object of a class, but the are also commonly used for constant information where you only need one copy of a piece of data.


Think about it : You have a room and a door to enter this room. If you want to check how who is coming in and secure your room, then you should use properties otherwise they won't be any door and every one easily come in w/o any regulation

class Room {
   public string sectionOne;
   public string sectionTwo;
}

Room r = new Room();
r.sectionOne = "enter";

People is getting in to sectionOne pretty easily, there wasn't any checking

class Room 
{
   private string sectionOne;
   private string sectionTwo;

   public string SectionOne 
   {
      get 
      {
        return sectionOne; 
      }
      set 
      { 
        sectionOne = Check(value); 
      }
   }
}

Room r = new Room();
r.SectionOne = "enter";

Now you checked the person and know about whether he has something evil with him





field