我有以下两个课程:
public class Foo : IFooOperations
{
public FooData Data { get; set; }
public FooUser User { get; set; }
public Foo(FooData fooData)
{
Data = fooData;
}
private async void SetupFoo()
{
...
}
public async void FooOp()
{
...
}
}
和
public class Bar : Foo, IBarOperations
{
public Foo(FooData fooData) : base(fooData)
{
}
public async void BarOp()
{
...
}
}
在给我一个Foo
对象之后,为什么Bar bar = (Bar)foo;
不允许我将其强制转换为Bar
对象?它会引发InvalidCastException: Specified cast is not valid.
异常。
在我看来,这应该行得通。 Bar
只是Foo
,并且有一个在状态上运行的附加方法,这两个对象都已经存在。
一些其他上下文:Bar
对象实际上是特权的Foo
用户,这些用户根据其数据被允许访问BarOp()
方法。我正在构建一个SDK,并希望(ab)使用强制转换机制默认情况下隐藏这些特权方法。我希望我的最终用户需要有意识地决定Foo
确实是Bar
并执行转换,然后才能访问BarOp()
方法。
有人对可能出什么问题,如何解决这个问题或要考虑的替代体系结构有任何想法吗?
答案 0 :(得分:0)
Bar只是Foo,仅在状态上操作了一个附加方法,这两个对象已经对它们通用。
这与强制转换是否起作用完全无关。如果引用的对象是目标类型或某个子类型的实例,则强制转换(在引用类型之间,忽略用户定义的转换)只能在.NET中成功。就这么简单。您可以有两个没有任何个额外成员的课程:
class Base {}
class Derived : Base {}
...并且如果您实际上拥有Derived
的实例时尝试转换为Base
,则转换仍将失败:
Base b = new Base();
Derived d = (Derived) b; // Exception
我希望我的最终用户需要有意识地确定Foo确实是Bar,并在能够访问BarOp()方法之前执行强制转换。
但是对象不是实际上是Bar
,否则强制转换将起作用。如果确保在任何时候都创建了 actual Bar
对象,那么您的计划将是正确的。
如果您不打算添加任何执行时安全性,只需让开发人员说“我真的是想这样做”,那么您可以编写包装类型:
class Bar : IBarOperations
{
// Keep a reference to the existing Foo object
// Expose privileged methods
}
然后,如果您想使用流利的样式,则可以为Foo
中的AsBar()
写一个实例或扩展方法,以构造一个新的Bar
,从而得到以下代码:>
foo.AsBar().BarOp();
这仍然保持了额外的“检查”(即使实际上并不能验证用户应该能够做到这一点),而无需尝试使用强制转换。