C# 无法将System.Delegate[]类型的对象强制转换为System.Action[T][]类型
我试图通过强制转换C# 无法将System.Delegate[]类型的对象强制转换为System.Action[T][]类型,c#,casting,delegates,C#,Casting,Delegates,我试图通过强制转换Delegate.GetInvocationList的返回值,从某个方法返回Action[]类型的对象,该对象属于Delegate[]。尝试执行此操作时会引发异常 下面的示例演示了我试图在一些较大的代码中实现的目标: using System; class Fish { } class FishDishes { public static void DishA(Fish f) { Console.WriteLine("Dish A"); } public s
Delegate.GetInvocationList
的返回值,从某个方法返回Action[]
类型的对象,该对象属于Delegate[]
。尝试执行此操作时会引发异常
下面的示例演示了我试图在一些较大的代码中实现的目标:
using System;
class Fish
{ }
class FishDishes
{
public static void DishA(Fish f) { Console.WriteLine("Dish A"); }
public static void DishB(Fish f) { Console.WriteLine("Dish B"); }
}
class FishSchef
{
protected Action<Fish> cookFishDish = null;
public void ShowOff()
{
System.Console.WriteLine("cooking every fish dish I know of!");
cookFishDish?.Invoke(new Fish());
}
public void LearnToCookNewDish(Action<Fish> new_dish)
{
cookFishDish += new_dish;
}
}
class SeniorFishSchef : FishSchef
{
// Mentor a Junior Schef by sending her an array of every dish Senior Schef knows of
public Action<Fish>[] MentorJuniorSchef()
{
return (Action<Fish>[]) cookFishDish.GetInvocationList();
}
}
class JuniorFishSchef : FishSchef
{
// Get mentored by a Senior Schef by adding sending her an array of every dish Senior Schef knows of
public void GetMentored(SeniorFishSchef senior)
{
Action<Fish>[] dishes_arr = senior.MentorJuniorSchef();
foreach (Action<Fish> fishdish in dishes_arr)
cookFishDish += fishdish;
}
}
class Test
{
public static void Main()
{
SeniorFishSchef senior = new SeniorFishSchef();
senior.LearnToCookNewDish(FishDishes.DishA);
senior.LearnToCookNewDish(FishDishes.DishB);
senior.ShowOff();
JuniorFishSchef junior = new JuniorFishSchef();
junior.GetMentored(senior);
junior.ShowOff();
}
}
使用系统;
分类鱼
{ }
鱼缸
{
公共静态无效DishA(Fish f){Console.WriteLine(“DishA”);}
公共静态无效DishB(Fish f){Console.WriteLine(“DishB”);}
}
FishSchef类
{
受保护操作cookFishDish=null;
公众虚张声势
{
System.Console.WriteLine(“烹饪我知道的每一道鱼菜!”);
烹饪鱼盘?.Invoke(新鱼());
}
公共空间学习烹饪新菜(行动新菜)
{
cookFishDish+=新的_盘;
}
}
类别:FishSchef
{
//指导一个初级Schef,向她发送一系列高级Schef知道的每道菜
公共行动[]导师JUnitorsChef()
{
return(Action[])cookFishDish.GetInvocationList();
}
}
类JuniorFishSchef:FishSchef
{
//得到高级Schef的指导,向她发送高级Schef知道的每道菜的数组
获得辅导的公共部门(高级Fishschef高级)
{
Action[]disks_arr=senior.MentorJuniorSchef();
foreach(盘子中的动作鱼盘)
烹饪鱼盘+=鱼盘;
}
}
课堂测试
{
公共静态void Main()
{
SeniorFishSchef senior=新的SeniorFishSchef();
高级烹饪新菜(Fishdisks.DishA);
高级烹饪新菜(fishdisks.DishB);
高级。炫耀();
JuniorFishSchef junior=新的JuniorFishSchef();
初级。获得指导(高级);
junior.shooff();
}
}
运行时,会引发以下异常:
未处理的异常:System.InvalidCastException:无法强制转换类型为的对象
“System.Delegate[]”以键入“System.Action'1[Fish][]”。
在SeniorFishSchef.MentorJuniorSchef()上[etc]
请帮助我理解:
[]]
)Delegate[]
,并制作相同类型的carr
1.为什么这样的演员阵容不可能
因为数组类型System.Delegate[]
与System.Action[]
不同,也不能将一个隐式转换为另一个。请注意,在C#中,存在一种类型差异形式,允许隐式转换到另一个方向(即从操作[]
到委托[]
),因为它保证操作[]
实例中的每个操作
元素实际上也是委托
。但是,从委托
到操作
,没有这样的保证,因此试图将委托【】
强制转换为操作【】
,是非法的
2.为什么编译器不发出错误
编写显式转换时,编译器通常假定您知道自己在做什么。它通常只有在确信强制转换将失败时才会发出错误(一个值得注意的例外涉及泛型,但将其拖到这里的讨论中会分散注意力)
请注意,由于从操作[]
转换为委托[]
(见上文)是合法的,因此实际上您可以有一个真正引用操作[]
实例的委托[]
引用。因此,在某些情况下,您尝试执行的强制转换可能会成功,因此编译器无法为此发出错误
当然,在这种特殊情况下,数组实际上只是Delegate[]
,而不是Action[]
,因此是运行时错误。但编译器无法确定情况是否如此
3.强制类型的符号是什么System.Action`1[Fish][]
-为什么它有两个下标([][]
)
Fish
周围的方括号不是数组表示法,而是指示泛型类型Action
的类型参数的一种方式。未构造的类型名称显示为Action`1
,其中`1
表示具有一个类型参数的泛型类型。第二组方括号表示数组类型
是的,有点混乱
至于替代方案,您当然可以只返回一个新数组,其中您已经从原始数组中复制了元素。一个简单的方法是:
return cookFishDish.GetInvocationList().Cast<Action<Fish>>().ToArray();
返回cookFishDish.GetInvocationList().Cast().ToArray();
由于您知道单个委托
对象实际上必须是操作
的实例,因此使用Enumerable.Cast()
方法分别强制转换每个对象,然后将生成的IEnumerable
对象转换回数组应该可以实现您想要的功能