1

我有一个委托期望 A 类型的参数作为参数。所以 A 是基类。B 类和 C 类继承自 A。

问题是B和C虽然继承了基类A,但是脚本底部的DoSomething函数却无法转换为delegate。

public class A { }
public class B : A { }
public class C : A { }

public delegate void CallbackAction(params A[] paremeters);
public class Main
{
    public int main(params string[] args)
    {
        CallbackAction callbackAction;
        callbackAction = DoSomething1;
        callbackAction = DoSomething2;
        callbackAction = DoSomething3;

        return 0;
    }

    public void DoSomething1(A arg0) { }
    public void DoSomething2(B arg0) { }
    public void DoSomething3(C arg0) { }
}

有没有办法在委托中使用 params 并能够使用以 params 类作为基类的类?

编译时我得到的错误是:错误 5 'DoSomething3' 没有重载匹配委托 'SKConsole.CallbackAction'

我正在使用 .NET 4 和 XNA

编辑:: 好的,让我解释一下我为什么要使用它,我正在创建一个控制台。这意味着使用我的控制台的程序员可以向控制台添加命令(console.AddCommand("help", Help),这里的帮助是一个函数。当您在游戏中并在控制台中输入帮助时,它将执行函数 Help() .我现在希望它也可以与 console.AddCommand("setSpeed", SetPlayerSpeed) 一起使用。SetPlayerSpeed 函数有 1 个参数,一个 int。但我希望它可以与任何函数一起使用,所以如果程序员创建函数 DoSomeFancyStuff(float a , string b, int c) 我希望控制台创建一个命令,如果您在控制台中输入正确的字符串,则执行这些命令。

我已经尝试为不同的功能制作很多代表,但在我看来这有点难看。

然后我尝试的是以下

public abstract class SKConsoleParameter
{
    protected string value;

    public SKConsoleParameter(string value)
    {
        this.value = value;
    }
    public string GetRawValue()
    {
        return value;
    }

    public abstract bool IsValid();
    public abstract object GetValue();
}

public class StringParam : SKConsoleParameter
{
    public StringParam(string value) : base(value) { }

    public override bool IsValid()
    {
        return true;
    }

    public override object GetValue()
    {
        return value;
    }
}

public class IntParam : SKConsoleParameter
{
    public IntParam(string value) : base(value) { }

    public override bool IsValid()
    {
        int i;
        return int.TryParse(value, out i);
    }

    public override object GetValue()
    {
        int i;
        if (int.TryParse(value, out i))
            return i;
        else
            return 0;
    }
}

这样做是因为如果开发人员创建了如下函数:

DoSomethingCool(StringParam s, IntParam i)

然后它可以通过使用 (string)s.GetValue() 和 (int)i.GetValue() 接收值 StringParam 和 IntParam 类都继承自 SKConsoleParameter,所以我现在可以创建以下委托

void CoolDelegate(params SKConsoleParameter[] parameters)

但这不起作用..因为这个页面顶部的A,B和C类的抽象问题

有没有人有任何想法来解决这个问题?

4

3 回答 3

1

您正在错误的地方寻找错误。C#允许在委托的输入参数中进行逆变。您的代码的问题是您的委托需要params A[],而您的方法需要一个A. 这是不允许的。Delcare 你的代表接受一个单一的A

delegate void Callback1 (B a) ;
void Test11 (A a) {}
void Test12 (B b) {}

Callback1 c11 = Test11 ; // OK
Callback1 c12 = Test12 ; // OK

另请注意,这不适用于数组参数:

delegate void Callback2 (B[] a) ;
void Test21 (A[] a) {}
void Test22 (B[] b) {}

Callback2 c21 = Test21 ; // compile error
Callback2 c22 = Test22 ; // OK
于 2013-02-27T14:19:58.237 回答
0

试试这个代码:

 public class A {  }
public class B : A { }
public class C : A { }

public static class Helper
{
    public static Action<A> DoSomething;
}

class Program
{
    static void Main(string[] args)
    {
        var a = new A();
        var b = new B();
        var c = new C();

        Helper.DoSomething = new Action<A>(DoSomething1);
        Helper.DoSomething = (Action<A>)new Action<B>(DoSomething2);
        Helper.DoSomething = (Action<A>)new Action<C>(DoSomething3);                       
    }

    public static void DoSomething1(A a) { }
    public static void DoSomething2(B a) { }
    public static void DoSomething3(C a) { }
}
于 2013-02-27T14:18:53.690 回答
0

根据您更新的代码 - 试试这个。只要您的方法与委托匹配,逆变就应该在 .NET 3.5 或更好的版本中按预期工作

public abstract class SKConsoleParameter
{
    protected string value;

    public SKConsoleParameter(string value)
    {
        this.value = value;
    }
    public string GetRawValue()
    {
        return value;
    }

    public abstract bool IsValid();
    public abstract object GetValue();
}

public class StringParam : SKConsoleParameter
{
    public StringParam(string value) : base(value) { }

    public override bool IsValid()
    {
        return true;
    }

    public override object GetValue()
    {
        return value;
    }
}

public class IntParam : SKConsoleParameter
{
    public IntParam(string value) : base(value) { }
    public override bool IsValid()
    {
        int i;
        return int.TryParse(value, out i);
    }
    public override object GetValue()
    {
        int i;
        if (int.TryParse(value, out i))
            return i;
        else
            return 0;
    }
}   

class Program
{

    public delegate void CoolDelegate(params SKConsoleParameter[] parameters);

    static void Main(string[] args)
    {
        var s = new StringParam("Glenn");
        var i = new IntParam("12");
        var coolDel = new CoolDelegate(DoSomethingCool);
        coolDel(s, i);
    }

    public static void DoSomethingCool(params SKConsoleParameter[] parameters)
    {
        if (parameters == null) throw new ArgumentNullException("parameters");
        foreach (var item in parameters)
        {
            if (item is IntParam)
            {
                // do something interesting
                continue;
            }

            if (item is StringParam)
            {
                // do something else interesting
                continue;
            }

            throw new NotImplementedException("unknown param type");
        }
    }
}
于 2013-02-27T19:54:12.883 回答