代码之家  ›  专栏  ›  技术社区  ›  sleath

C代表实际使用情况[重复]

  •  6
  • sleath  · 技术社区  · 16 年前

    这个问题已经有了答案:

    我以前问过一个关于代理的问题,是否有人有一个必须使用代理的场景?这是如何改进我的C代码的?

    正如我在很多场景中使用它一样,我似乎总是能够围绕它进行编程。

    11 回复  |  直到 16 年前
        1
  •  3
  •   Tom Ritter    16 年前

    假设你不是在谈论事件-当然你可以围绕它编程。关键是要做到 更好的 清洁剂 .

    protected void Sort()
    {
        foreach (string key in _dBase.Keys)
        {
          Array.Sort<Pair<string, Dictionary<string, T>>>(_dBase[key], 
                new Comparison<Pair<string, Dictionary<string, T>>>(
            delegate(Pair<string, Dictionary<string, T>> a, Pair<string, Dictionary<string, T>> b)
            {
                if (a == null && b != null)
                    return 1;
                else if (a != null && b == null)
                    return -1;
                else if (a == null && b == null)
                    return 0;
                else
                    return a.First.CompareTo(b.First);
            }));
        }
    }
    

    我可以在没有内联委托的情况下这样做吗?当然。我的类中会有一个只能用于这个实例的软盘私有方法吗?是的。

    编辑: 如注释中所述,您可以简化:

    Array.Sort<Pair<string, Dictionary<string, T>>>(_dBase[key], 
       new Comparison<Pair<string, Dictionary<string, T>>>(
       delegate(Pair<string, Dictionary<string, T>> a, Pair<string, Dictionary<string, T>> b)
       {
    

    Array.Sort<Pair<string, Dictionary<string, T>>>(_dBase[key], (a,b) =>
       {
    
        2
  •  4
  •   Yuriy Faktorovich    16 年前

    无论何时使用 Strategy Pattern 或者是观察者模式,委托使您的工作比使用接口容易得多。

        3
  •  3
  •   Daniel Earwicker    16 年前

    如果您设想C没有委托,那么您通常会遇到这样的情况:您使用一个方法拥有类或接口。该方法的名称是多余的。例如

    public interface IGetMail
    {
        Mail JustGetTheMail();
    }
    

    接口就是关于那个方法的。对该类型对象的引用实际上只不过是对单个可调用方法的引用。呼叫代码:

    Mail m = getMail.JustGetTheMail();
    

    可以简化为:

    Mail m = getMail();
    

    编译器可以像“语法糖”一样做到这一点而不产生任何歧义,因为只有一个方法可以调用它 getMail 参考文献。

    所以让我们把这个特性添加到C编译器中。现在,在声明这些类型时,我们也可以使它更整洁一些。我们在调用方法时不需要指定方法名,那么为什么我们首先要给方法命名呢?

    让我们选择一个标准方法名, Invoke ,即

    public interface IGetMail
    {
        Mail Invoke();
    }
    

    我们将添加更多的句法糖分,以允许我们将其写为:

    public delegate Mail GetMail();
    

    嘿!我们已经将委托添加到C编译器中。

    (从技术上讲,clr也知道委托,因此,C编译器不生成接口,而是生成一个特殊的“委托”类型,它支持异步调用,并操作不可变的委托列表,并将其视为单个引用;但在基本形式中,它可以通过接口完成。有一个建议,为Java做这件事。

    然后我们可以进一步添加匿名委托——使它们简洁地以接口不是的方式实现。

    因此,要回答您的问题-任何时候只要您的接口有一个方法,它就可能是一个委托,并且您将能够认真地减少必须编写的垃圾代码的数量。

        4
  •  3
  •   Stan R.    16 年前

    没有人提到过这一点,但是如果您在lambda中使用linq,那么您总是使用匿名方法。技术上仍然是 代表们 .

    假设你有一个叫人的班级

    class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
    

    你想实现一个查找方法,在那里你可以根据名字找到那个人。

    public Person Where(List<Person> list, string firstName)
    {
       //find the string
       foreach(Person item in list)
          if(item.FirstName.Equals(firstName))
            return item;
    }
    

    这是一个非常具体的搜索,而不是非常动态的搜索,这意味着如果你想用姓氏搜索,你必须更改这个方法或编写一个新的方法。

    幸运的是,Linq提供了一个名为 在哪里? 你需要通过 代表 ,您可以在匿名方法的帮助下即时创建。

    例如

    string searchString = "Stan";
    list.Where( person => person.FirstName.Equals(searchString));
    

    但是如果你想改成用姓搜索,你只需这么做

    string searchString = "R";
    list.Where( person => person.LastName.Equals(searchString));
    

    这个例子可能不是您要找的,但我只是想说明,有时我们总是使用代理,而没有考虑它或意识到它。

        5
  •  3
  •   Shankar R10N    16 年前

    实际使用:

    1. 假设有一个简单的用户控件调用 棋盘格 -它只包含两个复选框——chka和chkb。
    2. 在用户控件中,可以通过实现chka和chkb的相应事件来控制选中/取消选中事件。

    3.现在,以一种新的赢的形式,当你拖入 棋盘格 …您的目标是确保单击chka时必须更改标签的背景色…lbl颜色选择器。

    请注意,lblColorPicker是一个存在于窗体中且未直接绑定到的控件 棋盘格 .

    你将如何做到这一点?

    答:

    1. 首先,必须为用户控件创建一个新事件 棋盘格 .
    2. 要创建这个新事件,首先要在用户控件中创建一个委托,然后将这个委托用作正在编写的新事件的定义类型。
    3. 然后这个事件必须映射到用户控件中的chka…事件。

    通过这种方式,您可以通过任何新表单中的新事件,通过引用事件,通过刚刚编写的委托来控制CHKA。

    所以,这对于现实世界的使用是非常重要的!

    这一目标 不能 通过写下学员来实现。

    如果你不这么认为,或者你需要更多的阐述,请告诉我。

        6
  •  2
  •   Florian Doyon    16 年前

    匿名委托使代码在某些情况下更具可读性(您无需转到其他方法即可查看属于您的方法的代码:

    WinForms示例

    class MyForm:Form{
    //...
    protected override void OnLoad(EventArg e){
       this.Cursor=Cursors.Wait();
       this.Enabled=false; 
    
       // do a long running DB operation without blocking the UI Thread
       ThreadPool.QueueUserWorkItem(state=>{
    
         DoLongDBOperation();
    
         // re enable the form
         BeginInvoke(new Action(()=>{ this.Cursor=Cursors.Default;this.Enabled=true;}));
    
       });
    }
    
        7
  •  1
  •   Foxfire    16 年前

    如果您向类中添加事件或执行任何异步操作(还有其他几个好的原因需要委托),则委托是绝对必须拥有的。好处是它是一种非常灵活的方法。

        8
  •  1
  •   Dinos    16 年前

    我认为您指的是定义自定义委托?

    EventHandler已经最小化了对自定义委托定义的要求,但是如果您想向方法签名添加其他参数,它们仍然有用。

        9
  •  1
  •   Charles Bretana    16 年前

    每当需要修改或更改winforms控件的任何属性时,都需要使用委托将控件传递回在其上创建控件的线程…仅举一个例子。

        10
  •  1
  •   Steve    16 年前

    一个例子是发布/子消息调度器。您需要向调度器注册事件,然后适当地调用它们。这允许您非常容易地连接不同的代码片段。我想不出一种不使用代理就可以做到这一点的方法

        11
  •  1
  •   Rodrick Chapman    16 年前

    假设您有一个控制台应用程序响应不同的按键:

                Action a = () => {/* Do Stuff*/};
                Action b = () => {/* Do Stuff*/};
                Action c = () => {/* Do Stuff*/};
                Action d = () => {/* Do Stuff*/};
                Action e = () => {/* Do Stuff*/};
                Action f = () => {/* Do Stuff*/};
                Action g = () => {/* Do Stuff*/};
                Action h = () => {/* Do Stuff*/};
                Action i = () => {/* Do Stuff*/};
                Action j = () => {/* Do Stuff*/};
    
                List<Action> actions = new List<Action>() {a,b,c,d,e,f,g,h,i,j};
    
                string line;
    
                while((line = Console.ReadKey().KeyChar) != 'q')
                {
                    if(line.isBetween_0_and_9())
                    {
                        actions[line.ParseInt()]();
                    }
                }
    

    显然,您可以使用大量的IFS,但这不仅简单,而且几乎可以肯定更清晰/可读。

    推荐文章