C#调用一个事件

时间:2014-12-01 00:31:02

标签: c# events event-handling

我在这里创建了这个程序,以展示我想要做的事情。您可以看到除了应该调用_OnSell事件的行之外,所有代码都已写入。 (第21行〜)

using System;

namespace example
{
    public class Car
    {
        public int Price;
        public string ModelName;
        private Boolean Sold;
        public delegate void SellEventHandler(string str);
        public event SellEventHandler _OnSell;
        public Boolean _Sold
        {
            get { return Sold; }
            set
            {
                Sold = value;
                if (Sold == true)
                {
                    // INVOKE _OnSell EVENT HERE !!
                }
            }
        }

        public void OnSell(string str)
        {
            Console.WriteLine("library stuff");
        }

        public Car(int price, string modelname)
        {
            Price = price;
            ModelName = modelname;
            Sold = false;
            _OnSell = OnSell;
        }
    }

    public class Program
    {
        static void Main()
        {
            Program p1 = new Program();
            Car _car = new Car(6000, "audi");
            _car._OnSell += p1.Car_OnSell;
            _car._Sold = Console.ReadLine() == "true" ? true : false;
            Console.ReadLine();
        }

        public void Car_OnSell(string message)
        {
            Console.WriteLine("user stuff");
        }
    }
}

每当值_car._OnSell发生变化时,我都会尝试调用事件_car._Sold。我怎么能在C#中做到这一点?

3 个答案:

答案 0 :(得分:2)

请参阅Handling and Raising Events

因此,按照提供的示例,代码如下所示。

请注意,名称会更改为更清晰的公共API以及事实上的一致性和命名标准。

public class Car
{
    // Note use of `sender` convention
    public delegate void SoldEventHandler(object sender, string str);

    // Events normally do not have the `On` prefix, also the event
    // name is normally the sense-correct verb such as `Sold` or `Selling`.
    public event SoldEventHandler Sold;

    private bool _isSold;
    public bool IsSold
    {
        get { return _isSold; }
        set
        {
            if (value && !_isSold) {
               // Only sell when false -> true
               OnSold("whatever string it is supposed to be");
            }
            _isSold = value;
        }
    }

    // "Typically, to raise an event, you add a method that is marked as protected and virtual.
    //  .. Name this method OnEventName; for example, OnDataReceived."
    public virtual void OnSold(string str)
    {
        // Follow the conventions in the link - ask on SO as to why the local
        // variable and check for null are important/necessary.
        var handler = Sold;
        if (handler != null) {
            handler(this, str);
        }
    }

// ..

    _car.Sold += p1.Car_OnSell;
    _car.IsSold += Console.ReadLine() == "true" ? true : false;

在大多数情况下,我建议让事件采用(object sender, EventArgs args),因为它会使事件的未来更改更加灵活 - 这也是链接中讨论的

答案 1 :(得分:2)

正如评论者提供的链接中所解释的那样(但遗憾的是,在发布的第一个答案中没有解释),您需要更改代码,使其看起来更像这样:

public Boolean _Sold
{
    get { return Sold; }
    set
    {
        Sold = value;
        if (Sold)
        {
            OnSell("your string here");
        }
    }
}

public void OnSell(string str)
{
    SellEventHandler handler = _OnSell;

    if (handler != null)
    {
        handler(str);
    }

    Console.WriteLine("library stuff");
}

以上将有效。但是,值得注意的是,您在几个重要方面偏离了正常的.NET事件处理习惯用法:

  1. 您的活动代表不遵循EventHandler<T>结构。正常的.NET方法签名提供了两个优点:识别发件人,以及基于事件参数的标准化EventArgs数据结构。
  2. 仅当属性设置为true时才会引发事件。更典型的,坦率地说更有用的是“改变”的事件。例如。 SoldChanged,会在Sold属性的值发生更改时随时生成。
  3. 遵循标准事件处理习惯用法的一个更好的好处是,您的类将与.NET中的大多数(如果不是全部)常见数据绑定实现一起使用。在这里实现它的方式,您的事件在使用方式上非常有限。在这种情况下可能没什么问题,但作为一般规则,提供更灵活的实现非常容易,你也可以养成这样做的习惯。

答案 2 :(得分:1)

试试这个:

_OnSell( "some message" );