65.9K
CodeProject 正在变化。 阅读更多。
Home

委托入门

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.39/5 (26投票s)

2007年10月16日

CPOL

4分钟阅读

viewsIcon

54464

入门 - 关于委托的基础知识,如何定义和使用它们

引言

委托是一个概念,但不知为何它总是令人困惑。我每次想使用委托时,仍然需要搜索它来确保语法正确。让我们看看是否能将委托简化到更容易理解的程度。这是一篇入门文章,非常非常基础,甚至没有涉及到事件。有很多文章解释委托和事件,但我认为很多人在阅读这些文章时感到困惑,因为你需要先理解基础知识。这是我尝试解释基础知识的尝试,我希望这有帮助,因为这是一个难以解释的话题。

定义:委托“被指定代表他人或他人行事的人”

// Define a new type in the system called MathFunction
private delegate int MathFunction( int n1, int n2 );

// Create a variable of type MathFunction, the type MathFunction has been defined above.
private MathFunction adderFunction;

委托是一个保存函数的变量。就这么简单,我可以定义一个 `MathFunction` 类型的变量并将我的一个函数赋给它,然后稍后,而不是调用一个特定的函数,我可以使用该变量就像函数一样调用它,它将调用之前分配给它的函数。

声明变量时可以使用多种类型。`int`、`string` 和 `boolean` 是可以使用的一些原生类型。开发人员可以通过在代码中定义 `Classes`、`Delegates`、`Enums` 和 `Structs` 来定义自己的类型。上面我们定义了一个名为 `MathFunction` 的新 `Delegate Type`。我们现在可以在声明变量时使用此类型。在上面的代码示例中,我们创建了一个名为 `adderFunction` 的变量,它的类型是 `MathFunction`。`MathFunction` 类型是一个委托,这意味着它可以像函数一样使用,并在执行时代表某个函数调用它。回到委托的原始定义:“*一个用于代表函数的变量*”。

Using the Code

// Define a new type in the system called MathFunction
private delegate int MathFunction( int n1, int n2 );

// Declare a variable that will hold a function of type MathFunction.
private MathFunction adderFunction;

static void Main()
{         
   // Assign the real function Add() to the variable adderFunction
   adderFunction = Add;

   // Call whatever function has been stored in the variable adderFunction
   int res = adderFunction( 1, 2 );
}

// This function matches exactly the signature defined in the MathFunction type
private int Add( int n1, int n2 )
{
   return n1 + n2;
}

我们在系统中创建了一个名为 `MathFunction` 的新类型,并使用该类型声明了一个名为 `adderFunction` 的变量。此变量被赋值给 `Add` 函数。变量 `adderFunction` 可以像函数一样被调用 `adderFunction(5, 10);`,它将调用实际的 `Add` 函数。

函数可以有不同的返回类型、参数数量和参数类型。我们定义了 `MathFunction` 委托类型,以明确表示声明为该类型的变量可以像一个接受两个 `int` 参数并返回 `int` 类型的函数一样使用。现在我们已经定义了此变量可以持有的函数的签名(或原型),我们可以将一个完全匹配该签名的实际函数赋值给该变量。

实际应用示例

你是否曾写过一个函数,它做了一堆事情,然后做一些具体的事情,然后又做了一堆事情。现在将该函数复制粘贴 5 次,只改变中间的 3 或 4 行具体代码…… 如果你能将几行代码作为参数传递进去,然后有一个函数完成所有的开销,但在中间运行那 3 或 4 行具体代码,那不是很棒吗?这是委托的一个经典示例。

例如,当你与 Web 服务器通信时,在实际的 Web 调用之前和之后有很多开销,例如日志记录、计时、错误处理等。`MakeWebCall()` 函数实现了所有这些开销,但你需要运行 3 或 4 行具体代码来解析响应。是的,有其他方法可以做到这一点,无需委托... 不要为每个你需要发出的服务器调用类型复制粘贴此函数,而是通过向 `MakeWebCall` 函数添加一个委托参数来处理此问题。此委托接收 `HttpWebResponse` 对象,执行其特定的解析逻辑,然后返回一个 `string`(或者可能引发一个错误)。请看下面的代码。

private delegate string dgProcessResponse( HttpWebResponse response );

// ----------------------------------- Below we pass in the delegate function.
private string MakeWebCall( string url, dgProcessResponse ProcessResponseFunction )
{
   string sResponse = String.Empty;
   try
   {
      // Setup logging
      // Setup Timing
      // Setup Web Request object

      // Call the Server
      HttpWebRequest req = WebRequest.Create( url ) as HttpWebRequest;
      HttpWebResponse response = req.GetResponse() as HttpWebResponse;

      // Always check that your delegate isn't null!
      if( ProcessResponseFunction != null )
      {
         sResponse = ProcessResponseFunction( response );  // <--- USE THE DELEGATE
      }
   }
   catch( Exception ex )
   {
      // Handle errors
      // Handle recoverable Logon Errors
   }
   finally
   {
      // End Timings
      // End Logon
   }
   return sResponse;
}

关注点

Andrew D. Weiss
软件工程师

小白也能懂的委托 - CodeProject - 代码之家
© . All rights reserved.