为什么这个委托任务不起作用以及如何解决?

时间:2015-07-23 09:13:13

标签: c# .net delegates covariance contravariance

我有以下示例代码:

<!--
To change this template use Tools | Templates.
-->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <title>Gopher Broke</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>

   <style>
    #gameCard td{
   padding:0; margin:0;
}

#gameCard {
   border-collapse: collapse;
   cursor:url(finger2.png), pointer;
}

    </style>

</head>
<body>
<center>
    <div id="container">
        <div id="header">
             <h1>GOPHER BROKE</h1>
             <center>You have 15 seconds to stop as many gophers as possible!</center>


             <div id="scoreOut">Score:</div>
            <FORM>
            <INPUT TYPE="button" onClick="history.go(0)" VALUE="Refresh">
            </FORM>
        </div>
        <div id="content">



            <table  id="gameCard">
                <tbody>

                    <tr>
                        <td id="cell00">&nbsp;</td>
                        <td id="cell01">&nbsp;</td>
                        <td id="cell02">&nbsp;</td>
                        <td id="cell03">&nbsp;</td>
                    </tr>
                    <tr>
                        <td id="cell10">&nbsp;</td>
                        <td id="cell11">&nbsp;</td>
                        <td id="cell12">&nbsp;</td>
                        <td id="cell13">&nbsp;</td>
                    </tr>
                    <tr>
                        <td id="cell20">&nbsp;</td>
                        <td id="cell21">&nbsp;</td>
                        <td id="cell22">&nbsp;</td>
                        <td id="cell23">&nbsp;</td>
                    </tr>
                    <tr>
                        <td id="cell30">&nbsp;</td>
                        <td id="cell31">&nbsp;</td>
                        <td id="cell32">&nbsp;</td>
                        <td id="cell33">&nbsp;</td>
                    </tr>
                    <tr>
                        <td id="cell40">&nbsp;</td>
                        <td id="cell41">&nbsp;</td>
                        <td id="cell42">&nbsp;</td>
                        <td id="cell43">&nbsp;</td>
                    </tr>
                    <tr>
                        <td id="cell50">&nbsp;</td>
                        <td id="cell51">&nbsp;</td>
                        <td id="cell52">&nbsp;</td>
                        <td id="cell53">&nbsp;</td>
                    </tr>
                </tbody>
            </table>
        </div>
    </div>

    <br>

    <!--<input id="btn" type="button" value="Play The Game!!" />-->

</center>

        <script>

            var score = 0;

            function game(){

       // var btn = document.getElementById('btn');

        //btn.addEventListener('click', UpdateTable);



// Set the max length and Width
var maxWidth = 4;
var maxLength = 6;


// Returns a random number
function CreateRandom() {
    return Math.floor(Math.random() * 4 + 1);
}



//function to create an image
function CreateGopher() {

    var randomNumber = CreateRandom();
    var image = "Sup";

    if(randomNumber == 1){
        image = "<img src='gopher.jpg' class='gopher' height='50' width='50'>";
    }
    else if(randomNumber == 2){
        image = "<img src='lettuce.jpg' class='lettuce' height='50' width='50'>";
    }
     else if(randomNumber == 3){
        image = "<img src='lettuce.jpg' class='lettuce' height='50' width='50'>";
    }
     else if(randomNumber == 4){
        image = "<img src='lettuce.jpg' class='lettuce' height='50' width='50'>";
    }

    return image;
}


//create table
function UpdateTable() {
    // Iterate over each cell and set a random number
    for (var i = 0; i < maxLength; i++) {
        for (var j = 0; j < maxWidth; j++) {
            tmp = 'cell' + i + j;
            document.getElementById(tmp).innerHTML = CreateGopher();
        }
    }



}

function newTable() {
    // Iterate over each cell and set a random number
    for (var i = 0; i < maxLength; i++) {
        for (var j = 0; j < maxWidth; j++) {
            tmp = 'cell' + i + j;
            document.getElementById(tmp).innerHTML = CreateGopher();
        }
    }



}

//Use The function update table
UpdateTable();





        $( ".lettuce" ).click(function() {
          //alert( "You Clicked on the lettuce" );
          score -= 5;

          document.getElementById("scoreOut").innerHTML = "<h1>Score :" + score;

        });

         $( ".gopher" ).click(function() {
          //alert( "You Clicked on the lettuce" );
          score += 5;

          document.getElementById("scoreOut").innerHTML = "<h1>Score :" + score;

        });

            }


    game();        
    setInterval(game, 1000);
    setTimeout(function () 

               {alert("Your Score is " + score)
                window.location.href = "startGame.html";  

                           }, 16000);        

    </script>




</body>
</html>

它抱怨委托任务。我怀疑这是由于协方差/逆变问题,老实说这是一个我不完全理解的概念。

有没有办法构建这个代码?我需要一个带有任何事件args的任何事件的通用处理程序(继承自EventArgs)。

5 个答案:

答案 0 :(得分:2)

想象一下,这行是编译的:

        this.del = this.EventHandler;

然后,这是一个问题:

        // since del must accept ANY EventArgs descendant, this should be possible:
        del.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add));
        // since del's signature IS (object, PropertyChangedEventArgs), we must convert 
        // NotifyCollectionChangedEventArgs to PropertyChangedEventArgs
        // OOOPS...
  

我需要一个带有任何事件参数的任何事件的通用处理程序

使用具有此签名的处理程序:

public void EventHandler(object sender, EventArgs e)
{

}


// compiles just fine
this.Loaded += EventHandler;
this.Closing += EventHandler;
this.Drop += EventHandler;

答案 1 :(得分:1)

您可以找到有关委托差异和协方差here

的说明
  

为代理,协方差和逆变分配方法时   提供将委托类型与方法匹配的灵活性   签名。协方差允许方法具有返回类型   比委托中定义的派生更多。逆变许可证   一个方法,其参数类型的派生类型少于   代表类型。

答案 2 :(得分:0)

方法签名必须与delegate匹配。如果允许您尝试执行的操作,则可以将任何类型传递给继承自EventArgs的第二个参数,但它实际上需要PropertyChangedEventArgs

答案 3 :(得分:0)

这不可能那样。在您的示例代码中,您的EventHandler方法要求ePropertyChangedEventArgs类型,即比委托声明的类型更具体的类型。

它将以相反的方式工作,即您的处理程序可能不如委托更具体。

答案 4 :(得分:0)

应该是

在方法重载中使用PropertyChangedEventArgs

因为将事件分配给任何代理人。他们的签名必须相同

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        this.del = this.EventHandler; <-- This does not build
    }

    public void EventHandler(object sender, PropertyChangedEventArgs e)
    {

    }

    public delegate void A(object sender, PropertyChangedEventArgs e);

    private A del;
}