C#中Python属性定制/JavaScript对象字面量的等价物

1 投票
2 回答
601 浏览
提问于 2025-05-01 03:10

我喜欢Python的一个原因是,它可以让你自定义属性的访问方式,具体可以参考这篇文档

class Foo(object):
    def __getattr__(self, name):
        if some_predicate(name):
            # ...
        else:
            # Default behaviour
            raise AttributeError

在JavaScript中,你也可以用对象字面量的方式更直接地做到类似的事情。

我想问的是:在C#中,怎么能实现类似的功能呢?重载'.'这个操作符是一个方法,但在C#中是不允许的。

我想的例子是定义一个类,像这样:

public class MyClass
{
    public IDictionary Properties {get; private set;}
    public MyClass(IDictionary properties)
    {
        this.Properties = properties;
    }

    // Overload the '.' operator - not allowed!
    public static object operator .(MyClass inst, string name)
    {
        return inst.Properties[name];
    }
}

使用这个类的方式如下:

class Program
{
    static void Main(string[] args)
    {
        IDictionary properties = new Dictionary<string, string>() {
            { "prop1", "value1"}, { "prop2", "value2"} };
        var my = new MyClass(properties);
        System.Console.WriteLine(my.prop1); // Doesn't work!
    }
}

(注意:我在这里问过一个关于C++的类似问题这里;最开始是同一个问题,但为了更具体,所以分开了针对每种语言。)

暂无标签

2 个回答

1

@galenus 给了我一个被接受的答案,但为了记录在案,我想把我的示例代码更新一下,使用 DynamicObject

public class MyClass : DynamicObject
{
    public IDictionary<string, object> Properties { get; private set; }
    public MyClass(IDictionary<string, object> properties)
    {
        this.Properties = properties;
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        return Properties.TryGetValue(binder.Name, out result);
    }
}


class Program
{
    static void Main(string[] args)
    {
        IDictionary<string, object> properties = new Dictionary<string, object>() {
            { "prop1", "value1"}, { "prop2", "value2"} };
        dynamic my = new MyClass(properties);
        System.Console.WriteLine(my.prop1);
    }
}
1

你可以直接使用内置的支持。你应该让你的类继承自DynamicObject,然后重写它的TryGetMember/TrySetMember方法,通过检查构造函数传入的字典来判断属性是否有效。

另一种选择是直接使用ExpandoObject,把它当作一个属性的集合。

不过,虽然你可以获得一些动态语言的功能,但你会失去C#的一些特性,比如类型安全、编译时检查和IDE的代码补全支持。

撰写回答