web-dev-qa-db-ja.com

パラメータが暗黙的に提供される関数

コールバック関数はいくつかのパラメーターを受け入れることができますが、関数を呼び出すときに明示的に宣言されていません。

これは実際どのように機能しますか?関数をパラメーターとして別の関数に渡し、そこにパラメーターを暗黙的に含めることを可能にしているのは何ですか?

例えば:

Javascript

$.get('somefile.php', {func : 'getUserNames'}).done(function(data){
    if(data)
       console.log(data); // '{"0" : "billy", "1" : "bobby"}'
    // This is a js ajax call to a php file. 
    // How exactly am I retrieving "data" ?
}, 'json');

C#

private void BeginReadingData(){
    NetworkStream stream = tcpClient.GetStream();
    stream.BeginRead(buffer, 0, bufferSize, MyCallBack, tcpClient);
}

private void MyCallBack(IAsyncResult ar){
    // Now I can operate on 'ar'
    // why and how? 
}

これは、プロセスを説明したり正しく説明したりする方法ではなく、使用方法を理解しているものです。

5
BarryBones41

一部のパラメーターを受け入れるコールバック関数を何と呼びますが、それらは関数を呼び出すときに明示的に宣言されていませんか?

よく分かりません。場合によっては、オブジェクトのメソッドは、オブジェクト自体を暗黙的なパラメーターとして持つと見なされる場合があります。

しかし、あなたの例のような暗黙のパラメーターを持つ関数呼び出しはありません。コールバックでは、関数を呼び出した結果を渡すのではなく、関数自体を渡します。

stream.BeginRead(buffer, 0, bufferSize,
    MyCallBack, /* <- Not a function call, just a reference to a function. */
    tcpClient);

コールバックに指定した関数。これらの場合、$.getおよびstream.BeginReadは、指定したコールバック関数を呼び出し、必要なパラメーターを明示的に指定します。

したがって、ここで欠落しているのは、stream.BeginReadの定義が次のようなものであることです。

public virtual ISyncResult BeginRead(
        byte[] buffer,
        int offset,
        int count,
        AsyncCallback callback,
        Object state
    ) {
    /* stuff */

    callback(ar); /* <-- called with explicit parameter */

    /* more stuff */
}
4
8bittree

一部のパラメーターを受け入れるコールバック関数を何と呼びますが、それらは関数を呼び出すときに明示的に宣言されていませんか?

あなたが何を話しているのか分かりません。

function(data)explicitlyは、匿名関数に対してdataという名前のパラメーターを宣言します。

private void MyCallBack(IAsyncResult ar)explicitlyarという名前の関数に対して、IAsyncResultという名前のパラメーターを型MyCallbackで宣言します。

それらは両方ともその識別子を関数の本体で利用可能にし、コンパイラ/インタープリタはその識別子解決を「この関数の最初の引数にアクセスする」に変換することを知っています。

2
Telastyn

C#では、コールバックは単なるデリゲートです。デリゲートはオブジェクト内でコールバックメソッドをラップし、そのオブジェクトはパラメーターとして渡されます。したがって、コールバック関数を渡すときは常に、イベントハンドラーを例に挙げると、そのイベントハンドラーはデリゲートオブジェクトにラップされています。これで、適切な呼び出し時刻になると、対応する要素(例では 'NetworkStream'オブジェクト)がコールバックが登録されているかどうかを確認します。見つかった場合(あなたの場合-'MyCallback'が登録されています)、登録されたコールバックを呼び出します。

JavaScriptでは、設計上、メソッドはオブジェクトそのものにすぎません。したがって、コールバック関数を渡すときは常に、オブジェクトを渡します。 JavaScriptはコンパイルするので、渡すコールバックの署名はチェックしません。適切な署名がある場合(たとえば、適切な数のパラメーターがある場合)、コールバックはすべての値を受け取ります。署名が一致しない場合、コールバックは結果の値を見逃します。

0
Kousik Pandey