【问题标题】:What does assignment to a bracketed expression mean in C#?在 C# 中,对括号表达式的赋值是什么意思?
【发布时间】:2022-01-28 13:25:55
【问题描述】:

我正在阅读 Avalonia 源代码,我偶然发现了这句话:

return new MenuFlyoutPresenter
{
    [!ItemsControl.ItemsProperty] = this[!ItemsProperty],
    [!ItemsControl.ItemTemplateProperty] = this[!ItemTemplateProperty]
};

我从未见过这样的语法。如果没有索引属性或 this[] 访问器,这些括号会做什么?如果它们所指的属性不是布尔值,为什么它们会用感叹号否定?,也许是某种空检查?

代码本身包含在以下cs文件中:

https://github.com/AvaloniaUI/Avalonia/blob/master/src/Avalonia.Controls/Flyouts/MenuFlyout.cs

我已经跟踪了代码,但我无法理解该语法的作用。

【问题讨论】:

  • 但是集合初始化器有花括号不是吗?另外,为什么它们被否定了?
  • 不,他们没有,请阅读我链接到的部分
  • @AleksanderStukov:集合初始化器分为两大类:用于列表和用于字典。这是用于字典的语法。另外,UED 不应该惹到 Raynor。

标签: c# collection-initializer


【解决方案1】:

这里发生了几件事。

一、语法:

var menu = new MenuFlyoutPresenter
{
    [key] = value,
};

collection initializer,是以下的简写:

var menu = new MenuFlyoutPresenter();
menu[key] = value;

该索引器被定义为here

public IBinding this[IndexerDescriptor binding]
{
    get { return new IndexerBinding(this, binding.Property!, binding.Mode); }
    set { this.Bind(binding.Property!, value); }
}

所以key 有一个IndexerDescriptor,而value 是一个IBinding

那么,这件事是怎么回事?

!ItemsControl.ItemsProperty

我们可以从您的链接中看到ItemsProperty 是一个DirectProperty<TOwner, TValue>,并且最终实现了! 运算符here

public static IndexerDescriptor operator !(AvaloniaProperty property)
{
    return new IndexerDescriptor
    {
        Priority = BindingPriority.LocalValue,
        Property = property,
    };
}

Avalonia 似乎喜欢重载诸如 !~ 之类的运算符来执行您可能没有预料到的事情(并且通常会使用一种方法)。在这种情况下,他们使用AvaloniaProperty 上的! 作为访问该属性绑定的简写。

【讨论】:

    【解决方案2】:

    一个相对简单的类展示了一种允许这种语法的方式:

    public sealed class Demo
    {
        public Demo this[Demo index] // Indexer
        {
            get => !index;
            set {} // Not needed to demonstrate syntax. 
        }
    
        public static Demo operator !(Demo item) => item;
    
        public Demo ItemsProperty        => _empty;
        public Demo ItemTemplateProperty => _empty;
    
        public Demo SomeMethod(Demo ItemsControl)
        {
            return new Demo
            {
                [!ItemsControl.ItemsProperty] = this[!ItemsProperty],
                [!ItemsControl.ItemTemplateProperty] = this[!ItemTemplateProperty],
            };
        }
    
        static Demo _empty = new();
    }
    

    注意事项:

    • Demo 实现 operator! 允许 ! 运算符 用于该类型的值(例如,!ItemsPropertySomeMethod() 初始化)。
    • Demo 实现了一个索引器,它允许在集合初始化器的右侧使用索引(通过this)。
    • 索引器还支持使用SomeMethod() 中使用的[x] = y 集合初始化语法。

    operator()! 运算符与 this[Demo] 索引器的组合启用了语法。

    【讨论】:

    • 那个!操作员的使用完全不是本能的。 (我不知道你的想法)。 '!'对我来说意味着“不”,所以!Foo 意味着“不是 foo”。然而这里它的意思是 foo。为什么需要它?
    • @pm100 我的答案中的代码只是展示语法如何工作的一个示例 - 显然在实际代码中 operator!() 应该实现实际做某事。但是,我个人认为 Avalonia 代码滥用了这些运算符,使代码非常不直观且难以阅读。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-07
    • 2015-04-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多