我之前曾问过一个关于代表的问题,是否有人必须拥有必须拥有代表的场景?这如何改善我的C#代码?
正如我使用它的场景一样,我似乎总是可以围绕它进行编程。
答案 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)
真实世界使用:
3.现在,在新的Win Form中,当您拖入 Checker ...时,您的目标是确保在单击chkA时您必须更改标签的背景颜色... lblColorPicker。
请注意,lblColorPicker是一种存在于表单中的控件,并不直接绑定到 Checker 。
您将如何实现这一目标?
<强>答案:强>
通过这种方式,您可以通过您刚刚编写的代理引用事件来控制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,但这不仅更容易,而且几乎可以肯定更清晰/可读。