我有一个委托期望A类参数作为参数。所以A是基类。 B类和C类继承自A.
问题是虽然B和C继承自基类A,但脚本底部的DoSomething函数无法转换为委托。
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是一个函数。当你在控制台中输入并输入帮助时,它将执行函数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)
然后它可以通过使用(字符串)s.GetValue()和(int)i.GetValue()来接收值 StringParam和IntParam类都继承自SKConsoleParameter,所以我现在可以创建以下代理
void CoolDelegate(params SKConsoleParameter[] parameters)
但是这不起作用..因为本页顶部的A,B和C类的抽象问题
有没有人有任何想法来解决这个问题?
答案 0 :(得分:1)
您正在错误的地方寻找错误。委托的输入参数中的C#allows逆变。代码的问题在于,您的委托需要params A[]
,而您的方法需要A
。这是不允许的。将您的代表视为接受单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
答案 1 :(得分: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) { }
}
答案 2 :(得分: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");
}
}
}