سؤال

هل C # لديه أي شيء مثل __getattr__ بايثون؟

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

وإليك ما يبدو قانون بلدي مثل الآن:

class Foo
{
    protected bool Get(string name, bool def)
    {
        try {
            return client.Get(name);
        } catch {
            return def;
        }
    }

    public bool Bar
    {
        get { return Get("bar", true); }
        set { client.Set("bar", value); }
    }

    public bool Baz
    {
        get { return Get("baz", false); }
        set { client.Set("baz", value); }
    }
}

وهنا ما أود:

class Foo
{
    public bool Get(string name)
    {
        try {
            return client.Get(name);
        } catch {
            // Look-up default value in hash table and return it
        }
    }

    public void Set(string name, object value)
    {
        client.Set(name, value)
    }
}

هل هناك أي طريقة لتحقيق ذلك في C # دون استدعاء Get مباشرة؟

شكرا،

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

المحلول

ولا. وعلى الرغم من C # يدعم تفكير، للقراءة فقط عليه (للجمعيات تحميل). وهذا يعني أنك لا تستطيع تغيير أي الأساليب والخصائص، أو أي غيرها من البيانات الوصفية. على الرغم من أنك قد إنشاء خاصية ديناميكية واصفا اياه بانه لن يكون مريحة للغاية - فإنه سيكون أسوأ من استخدام طريقة Get الخاص بك. وبصرف النظر عن استخدام Dictionary<string, object> ومفهرس للفئة الخاصة بك، ليس هناك أشياء أخرى كثيرة يمكنك القيام به. على أي حال، لا تقوم القاموس أفضل إذا كان لديك أن العديد من الخصائص؟

وبيثون لا يتحقق في حالة وجود سمة في "وقت التحويل البرمجي" (أو الحمل لمرة على الأقل). C # لا. وهذا هو الفرق الأساسي بين اللغتين. في بيثون يمكنك القيام به:

class my_class:
    pass

my_instance = my_class()
my_instance.my_attr = 1
print(my_instance.my_attr)

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

نصائح أخرى

ولست متأكدا، ولكن ربما الميزات الديناميكية الإصدار 4.0 سوف تساعدك في ذلك. سوف تضطر إلى الانتظار على الرغم من ...

هل لي أن أسأل: <م> لماذا لا تريد الخصائص الفردية؟ هذه هي الطريقة. NET الاصطلاحية للتعبير عن البيانات المرتبطة كائن.

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

    protected T Get<T>(string name, T @default)
    {
        var prop = GetType().GetProperty(name);
        if(prop == null) return @default;
        return (T) prop.GetValue(this, null);
    }

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

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

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

using System;
using System.Collections.Generic;

namespace Program
{
    class Program
    {
        static void Main(string[] args)
        {
            MyList<int> list = new MyList<int>();
            // Add a property with setter.
            list["One"] = 1;
            // Add a property with getter which takes default value.
            int two = list["Two", 2];
            Console.WriteLine("One={0}", list["One"]);
            Console.WriteLine("Two={0} / {1}", two, list["Two"]);
            try
            {
                Console.WriteLine("Three={0}", list["Three"]);
            }
            catch
            {
                Console.WriteLine("Three does not exist.");
            }
        }
        class MyList<T>
        {
            Dictionary<string, T> dictionary = new Dictionary<string,T>();

            internal T this[string property, T def]
            {
                get
                {
                    T value;
                    if (!dictionary.TryGetValue(property, out value))
                        dictionary.Add(property, value = def);
                    return value;
                }
            }
            internal T this[string property]
            {
                get
                {
                    return dictionary[property];
                }
                set
                {
                    dictionary[property] = value;
                }
            }
        }
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top