簡體   English   中英

C#中的后備訪問器?

[英]Fallback accessors in C#?

C#是否有類似Python的__getattr__東西?

我有一個具有許多屬性的類,並且它們都共享相同的訪問者代碼。 我希望能夠完全刪除各個訪問器,就像在Python中一樣。

這是我的代碼現在的樣子:

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>和一個索引器之外,您還可以做很多其他事情。 無論如何,如果您擁有那么多屬性,做字典是否更好?

Python不會在“編譯時”(或至少在加載時)檢查屬性是否存在。 C#可以。 這是兩種語言之間的根本區別。 在Python中,您可以執行以下操作:

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);
    }

當然,如果您不關心定義的屬性本身,那么可以使用索引器和查找(例如字典)。 您還可以使用postharp進行某些操作,以將一組屬性轉換為一個屬性包-但是可能不值得。

如果您希望這些屬性可用於數據綁定和運行時發現,但不能在編譯時對其進行定義,那么您將需要查看動態類型描述符;否則,請參見圖4。 ICustomTypeDescriptorTypeDescriptionProvider相當多的工作,但用途廣泛(如果需要更多信息,請告訴我)。

這與使用動態屬性名稱的Python不同,但是您可能會發現它很有用:

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 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM