c# - 将抽象转换为派生实现的接口
问题描述
我听说在 c# 中向上转换是在编译时完成的,所以使用起来真的很便宜。但是我有这种情况,我希望转换的类型是抽象的,并且它不直接实现我希望转换的接口。
这是一个示例:
public interface ISomething
{
void Method();
}
public abstract class Base { }
public class Derived : Base, ISomething
{
public void Method() { }
}
public class OtherDerived : Base, ISomething
{
public void Method() { }
}
public class SomeClass
{
private Base[] _baseArray;
public void SomeMethod()
{
foreach (var item in _baseArray)
((ISomething) item).Method();
}
}
显然,我处于这样一种情况,其中的每个项目_baseArray
实际上都是继承自Base
并实现的类型ISomething
。但是由于我不能确定每个项目之间的类型Derived
,或者继承自和实现OtherDerived
的任何其他类型,我必须使用抽象基类型的数组。Base
ISomething
当然我可以使用一个数组ISomething
,但是我使用 Unity 并且接口在编辑模式下不会被序列化,我需要序列化该数组。
所以,既然上下文在这里,我的问题是:在编译时处理item
转换吗?ISomething
如果不是,它是否足够便宜,可以经常进行(准确地说是在每一帧)?
感谢您的关注,如果我不是很清楚,对不起,我不是英语,所以这并不容易。
编辑:感谢更好的标题
解决方案
你可以看到你的 C# 编译成的 IL:SharpLab IL 结果
你的循环:
// loop start (head: IL_0021)
IL_000d: ldloc.0
IL_000e: ldloc.1
IL_000f: ldelem.ref
IL_0010: stloc.2
IL_0011: ldloc.2
IL_0012: castclass ISomething
IL_0017: callvirt instance void ISomething::Method()
IL_001c: nop
// sequence point: hidden
IL_001d: ldloc.1
IL_001e: ldc.i4.1
IL_001f: add
IL_0020: stloc.1
IL_0021: ldloc.1
IL_0022: ldloc.0
IL_0023: ldlen
IL_0024: conv.i4
IL_0025: blt.s IL_000d
// end loop
Method()
被称为 using callvirt
,这基本上意味着调度。在这种情况下,这是因为您的对象的具体类型在编译时是未知的。
不过,我不会担心这个的性能,除非你分析并且你看到这个特定的代码是一个热点。
推荐阅读
- android - Kotlin - 从字节中检索位位置并将其转换为 int
- python - Python:在“apply_async”中使用外部函数
- sql - 编写 SQL 查询计算卡中的余额
- css - 关键帧动画在其他浏览器中不起作用
- javascript - 点亮元素事件侦听器不会强制重新渲染
- css - CSS:如果空间允许,从垂直切换到水平
- typescript - 字符串枚举作为 TypeScript 中的对象索引类型
- c# - Xamarin.Forms 更改所有 App 中的 Default FontFamily
- json - Instagram 嵌入帖子在 wordpress 上不起作用
- python-3.x - 在python中使用mega api上传图像时出现问题