【问题标题】:Assigning events in object initializer在对象初始化器中分配事件
【发布时间】:2020-08-20 15:09:00
【问题描述】:

为什么不能在 C# 的对象初始值设定项中分配事件和属性?这样做似乎很自然。

var myObject = new MyClass()
     {
        Property = value,
        Event1 = actor,
        // or
        Event2 += actor
     };  

或者有什么我不知道的技巧?

【问题讨论】:

标签: c# .net events delegates object-initializers


【解决方案1】:

这并没有使 C# 6 或 C# 7 成为 C# 6 或 C# 7(因为原始问题),但尚未决定反对。 GitHub 上有一个跟踪语言提案的问题。您可以在那里投票,也可以点击链接进入之前关于该功能的讨论。

https://github.com/dotnet/csharplang/issues/307

如果您想查看此功能,请为该问题点赞以帮助提高其知名度。

建议的语法是:

var timer = new DispatcherTimer {
    Tick += delegate {},
    Interval = TimeSpan.FromSeconds(1d),
};

【讨论】:

    【解决方案2】:

    就外部合约而言,事件没有设置器,只有add 和remove 方法 - 订阅者可以从事件中注册和注销,publishing 对象通过“引发”事件来决定何时调用回调。因此,“分配事件”的想法通常是没有意义的。

    但是,当您在类中声明一个事件时,C# 编译器为您提供了一个真正方便的功能:当您不提供自己的实现时,它会创建一个 private,为您提供支持委托字段,以及适当的添加/删除实现。这允许您在类内而不是在类外“设置事件”(实际上是支持字段)。要理解这一点,请考虑:

    public class Foo
    {
        // implemented by compiler
        public event EventHandler MyEvent;
    
        public static Foo FooFactory(EventHandler myEventDefault)
        {
           // setting the "event" : perfectly legal
           return new Foo { MyEvent = myEventDefault }; 
        }
    }
    
    public class Bar
    {
        public static Foo FooFactory(EventHandler myEventDefault)
        {
            // meaningless: won't compile
            return new Foo { MyEvent = myEventDefault };
        }
    }
    
    
    public class Baz
    {
        // custom implementation
        public event EventHandler MyEvent
        {      
            add { }  // you can imagine some complex implementation here
            remove { } // and here
        }
    
        public static Baz BazFactory(EventHandler myEventDefault)
        {
            // also meaningless: won't compile
            return new Baz { MyEvent = myEventDefault };
        }
    }
    

    【讨论】:

    • 这与限制无关。属性具有 setter 方法和私有支持字段,但对象初始化器可以很好地处理这些。
    【解决方案3】:

    您只能将运算符 += 或 -= 用于其所有者类之外的事件。

    public class Data
    {
        public event EventHandler OnSave = (s,e) => 
            {
                //do something important!
            };
    
        public void Save()
        {
            OnSave(this,null);
            //do save
        }
    }
    
    //outside the class
    Data data = new Data { OnSave = null }; //compile error
    data.OnSave = SomeMethodElse;  //compile error
    data.OnSave += MyCustomActionsOnSave;  //ok
    data.Save();
    

    您不能删除类中定义的OnSave 操作。您只能在课堂外添加/删除自己的OnSave 操作。如果删除event 关键字,OnSave 将不再是一个事件,而是一个普通的委托。然后你可以做任何事情,包括在类外赋值。

    【讨论】:

    • 他是(想要)使用+=。
    猜你喜欢
    • 2012-11-17
    • 1970-01-01
    • 2020-01-03
    • 2018-06-26
    • 2013-06-27
    • 2010-09-14
    • 2011-12-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多