C#代表真实世界的用法

时间:2009-10-15 15:50:35

标签: c# .net asp.net

我之前曾问过一个关于代表的问题,是否有人必须拥有必须拥有代表的场景?这如何改善我的C#代码?

正如我使用它的场景一样,我似乎总是可以围绕它进行编程。

11 个答案:

答案 0 :(得分:4)

每当您使用Strategy Pattern或观察者模式时,委托使您的工作比使用接口更容易。

答案 1 :(得分:3)

假设你不是在谈论事件 - 当然你可以围绕它进行编程。关键是要使其更好更清洁

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 :(得分:3)

如果您想象没有委托的C#,您通常会遇到使用一种方法拥有类或接口的情况。该方法的名称是多余的。 e.g。

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执行此操作。

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

所以回答你的问题 - 任何时候你的界面有一个方法,它可能是一个委托,你将能够认真减少你必须编写的垃圾代码的数量。

答案 3 :(得分:3)

没有人提到这一点,但如果您使用LINQ和Lambda,则始终使用匿名方法。技术上仍然是代表

假设您有一个名为Person的课程

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

并且您希望实现一种find方法,您可以根据其FirstName

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

这是一个非常具体的搜索,而不是非常动态,这意味着如果您想通过LastName进行搜索,则必须更改此方法或编写新方法。

幸运的是,LINQ提供了一个名为 Where 的扩展方法,您需要传递委托,您可以借助匿名方法动态创建 。

例如

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

但如果您想更改为按LastName搜索,则只需执行此操作

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

这个例子可能不是你想要的,但我只是想表明,有时候我们会一直使用代表而不考虑它或实现它。

答案 4 :(得分:3)

真实世界使用:

  1. 假设您有一个名为 Checker 的简单用户控件 - 它只包含2个复选框 - chkA和chkB。
  2. 在用户控件中,您可以通过实现chkA和ChkB的相应事件来控制检查/取消选中事件
  3. 3.现在,在新的Win Form中,当您拖入 Checker ...时,您的目标是确保在单击chkA时您必须更改标签的背景颜色... lblColorPicker。

    请注意,lblColorPicker是一种存在于表单中的控件,并不直接绑定到 Checker

    您将如何实现这一目标?

    <强>答案:

    1. 首先,您必须为用户控件 Checker 创建一个新事件。
    2. 要创建这个新事件,首先要在用户控件中创建一个委托,然后使用此委托作为您正在编写的新事件的定义类型。
    3. 然后,此事件必须映射到用户控件中的chkA ...事件。
    4. 通过这种方式,您可以通过您刚刚编写的代理引用事件来控制chkA ...来自任何新表单的新事件。

      因此,对于真实世界的使用非常重要!

      这个目标不能可以通过编写代表来实现。

      如果您不这么认为,请告诉我......或者您是否需要更多详细说明。

答案 5 :(得分:2)

匿名委托在某些情况下使代码更具可读性(您不必转到另一种方法来查看属于您的方法的代码:

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;}));

   });
}

答案 6 :(得分:1)

如果你向你的班级添加事件或做任何异步的事情,代表是绝对必须的(有几个其他很好的理由让代表参加)。好处是它是一种非常灵活的方法。

答案 7 :(得分:1)

我认为你指的是定义自定义代理?

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

答案 8 :(得分:1)

每当您需要修改或更改winForms控件的任何属性时,您需要使用委托将控制权传递回创建控件的线程...仅举几个例子中的一个。

答案 9 :(得分:1)

一个例子是发布/订阅消息调度程序。您需要向调度程序注册事件,然后适当地调用它们。这使您可以非常轻松地连接不同的代码片段。如果不使用代理

,我想不出办法

答案 10 :(得分:1)

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

            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,但这不仅更容易,而且几乎可以肯定更清晰/可读。