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
来实现这个目的?
谢谢,
答案 0 :(得分:2)
没有。虽然C#支持反射,但它是只读的(对于加载的程序集)。这意味着您无法更改任何方法,属性或任何其他元数据。虽然你可以create a dynamic property,但调用它不会很方便 - 它会比使用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
是否存在。
答案 1 :(得分:1)
我不确定,但也许版本4.0的动态功能可以帮助你。你不得不等待......
答案 2 :(得分:1)
我可以问:为什么你不想要个人财产吗?这是表达与对象关联的数据的惯用.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将一组属性变成一个属性包 - 但可能不值得。
如果您希望这些属性可用于数据绑定和运行时发现,但无法在编译时定义它们,那么您需要查看动态类型描述符; ICustomTypeDescriptor
或TypeDescriptionProvider
- 这是一项相当多的工作,但非常通用(如果您想了解更多信息,请告诉我)。
答案 3 :(得分:0)
这与使用动态属性名称在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;
}
}
}
}
}