30

我正在阅读 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

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

4

2 回答 2

35

这里发生了几件事。

一、语法:

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

是一个集合初始化器,是以下的简写:

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

该索引器在此处定义为:

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

我们可以从您的链接中看到ItemsPropertyDirectProperty<TOwner, TValue>它最终在此处!实现了运算符:

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

Avalonia 似乎喜欢重载运算符,例如!and~来做你可能没想到的事情(并且通常会使用一个方法)。在这种情况下,他们使用!onAvaloniaProperty作为访问该属性绑定的简写。

于 2022-01-28T13:37:32.873 回答
12

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

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()初始化中)。
  • Demothis实现一个索引器,它允许在集合初始化器的右侧使用索引(通过)。
  • 索引器还支持[x] = y使用SomeMethod().

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

于 2022-01-28T13:41:15.723 回答