我有一个界面和两种派生自它的类型。
但是,我无法做到以下几点:
B objectB = (B) objectA
其中B派生自Interface1(我正在编写类的名称,但该点仍然存在),同样对于objectA(类型A)。我收到以下错误消息:
无法将A类型的表达式转换为B.
这两种类型都来自界面,我缺少什么?
答案 0 :(得分:38)
答案 1 :(得分:6)
如果您共享的所有内容都是公共接口,则无法转换或转换为A
,除非您实际定义了自己的转换运算符,假设您控制其中一种类型的来源,或者使用另一个由 控制源的人提供的用户定义转换。 (但是,这种用户定义的转换不会保留原始对象。一个对象进入转换,出现另一个对象。)
您可以从B
转换为A
,将Interface1
转换为B
。但是两种类型只是共享一个共同的父级并不会使这两种类型可以将转换为另一种。
Interface1
tobias86在下面的评论中写得很好,你有一只猫和一只狗。两者都来自A a = new A();
B b = new B();
Interface1 obj1 = a; // legal
Interface1 obj2 = b; // legal
B obj3 = (B)a; // not legal, a is simply not a B
。但是一只猫不是一只狗。
作为扩展,您可能正在努力使用界面的方式和原因。您不使用接口将A替换为B,将B替换为A.您可以使用它替换A或B替换 Interface1 。这是您期望的界面,以及您可能提供的A或B.给出:
Animal
或
public void DoSomething(Interface1 obj) { } // expects
DoSomething(new A()); // you can supply A
这是您编程的界面,A和B仅仅是实现。你可能认为你可以将B传递给期望A的东西。期望可能需要改变。
答案 2 :(得分:3)
这两种类型实现相同的接口(或者具有相同的基本类型)这一事实并不能使它们互换; A
始终为A
,B
始终为B
。在继承链中,对象可以作为自身或任何父类型进行转换。你有:
A : ISomeInterface
B : ISomeInterface
可让您将A
投放为A
或ISomeInterface
,B
投放为B
或ISomeInterface
或(取决于“衍生自”的含义)
SomeBaseType
> A
> B
可让您将A
投放为A
或SomeBaseType
,B
投放为B
或SomeBaseType
(在每种情况下加object
)
答案 3 :(得分:3)
一个对象可以分配给祖先或其实现的接口,但不能分配给同级(即,从公共祖先派生的另一种类型);但是,您可以声明自己的显式转换:
class FooObject : IObject
{
public string Name { get; set; }
public int Value { get; set; }
public static explicit operator FooObject(BarObject bar)
{
return new FooObject { Name = bar.Name, Value = bar.Value };
}
}
class BarObject : IObject
{
public string Name { get; set; }
public int Value { get; set; }
public static explicit operator BarObject(FooObject bar)
{
return new BarObject { Name = bar.Name, Value = bar.Value };
}
}
现在您可以写
var foo = new FooObject();
var bar = (BarObject)foo;
或
var bar = new BarObject();
var foo = (FooObject)bar;
没有错误。
如果感觉很自然,您也可以创建implicit
转换。例如。 int
可隐式转换为double
:int i = 5; double x = i;
。
(这也是对已解决问题How do I cast Class FooObject to class BarObject which both implement interface IObject?的回答)。
答案 4 :(得分:1)
从A转换为B B时必须是A的超类型或者对象的运行时类型必须是B
如果你有
class A : B{}
您可以将编译时类型A的对象强制转换为B.如果对象的运行时类型为A,则还可以将B类型转换为A
在您的情况下,这两种类型不共享超级子类型关系。他们只共享一个共同的超类型,但这还不够。
作为一个例子,为什么这不能正常工作(一般来说)如何将编译器从Point[]
转换为Dictionary<string,HashSet<byte>>
? (均实现IEnumerable)
答案 5 :(得分:0)
你想做的事没有意义。 objectA
不是B
。
答案 6 :(得分:0)
您只能将它们转换为接口类型。 A不是B,但它们都是我。这意味着你可以拿A并施放到I或B并施放给我但不是B而是施放给A
答案 7 :(得分:0)
您需要转换为界面。
interface IBase { }
class A : IBase { }
class B : IBase { }
有了这个,这两种类型的共同点就是接口成员。 B
可能包含A
没有的项目。
A a = new A();
B b = new B();
IBase aBase = a;
IBase bBase = b;
然后,您可以在IBase
界面上调用任何内容。
答案 8 :(得分:0)
想象一下以下设置:
public interface Human
{
bool Male { get; }
}
public class Man : Human
{
public bool HasABeard { get { return true; } }
public bool IsMale { get { return true; } }
}
public class Woman : Human
{
public bool IsMale { get { return false; } }
public List<Pair<Shoe>> Shoes { get; set; }
}
您希望编译器从以下代码中生成什么?输出会是什么?
Man a;
Woman b = new Woman();
a = (Man)b;
Console.WriteLine(a.HasABeard ? "Beard ON" : "Beard OFF");