代码:
public interface IAssignable
{
IAssignable AssignMe { get; set; }
}
public class GenericAssignExample<T> where T : IAssignable
{
private T _assignable;
public void Valid(T toAssign)
{
_assignable.AssignMe = toAssign;
}
public void AlsoValid(T toAssign)
{
_assignable.AssignMe = toAssign.AssignMe;
}
public void AlsoValidAsWell(T toAssign)
{
_assignable = toAssign;
}
public void Invalid(T toAssign)
{
_assignable = toAssign.AssignMe;
}
}
问题:
在最后一个示例中,方法_assignable
(T where T is IAssignable
)无法赋值toAssign.AssignMe
(类型为IAssignable
),编译器抛出
“无法将类型'IAssignable'隐式转换为'T'”。
这是为什么? T
是IAssignable
,所以肯定可以为IAssignable
分配一个实例吗?
答案 0 :(得分:1)
这是为什么? T是IAssignable所以肯定可以为它分配一个IAssignable实例吗?
啊,不是吗? T
不 IAssignable
,如果是,则不需要Generics。 T
只是实现 IAssignable
。
仅仅因为Button
和TextBox
继承自Control
(或虚构的示例工具IControl
)并不意味着您可以将TextBox
分配给Button
,反之亦然。
public interface IAssignable
{
IAssignable AssignMe { get; set; }
}
public class A : IAssignable
{
public IAssignable AssignMe { get; set; }
}
public class B : IAssignable
{
public IAssignable AssignMe { get; set; }
}
// You will be able to instantiate this class with either A or B and both must be valid
public class GenericAssignExample<T> where T : IAssignable
{
// here, T refers to either A or B.
private T _assignable;
public void Valid(T toAssign)
{
// assigning either an A or B to the interface...
// always valid, both implement it
_assignable.AssignMe = toAssign;
}
public void AlsoValid(T toAssign)
{
// assigns interface to interface. Always valid.
_assignable.AssignMe = toAssign.AssignMe;
}
public void AlsoValidAsWell(T toAssign)
{
// assigns either an A to an A
// or a B to a B.
// both always valid.
_assignable = toAssign;
}
public void Invalid(T toAssign)
{
// this tries to assign an interface to either an A or a B
// always invalid.
_assignable = toAssign.AssignMe;
}
}
答案 1 :(得分:0)
将它投射到IAssingable:
_assignable.AssignMe = (IAssignable)toAssign;
答案 2 :(得分:0)
我认为我知道你感到困惑的地方,请注意差异
public interface IAssignable
{
IAssignable AssignMe { get; set; }
}
public class GenericAssignExample
{
private IAssignable _assignable;
public void Valid(IAssignable toAssign)
{
_assignable.AssignMe = toAssign;
}
public void AlsoValid(IAssignable toAssign)
{
_assignable.AssignMe = toAssign.AssignMe;
}
public void AlsoValidAsWell(IAssignable toAssign)
{
_assignable = toAssign;
}
public void Invalid(IAssignable toAssign)
{
_assignable = toAssign.AssignMe;
}
}
现在它应该按照你的意图工作。但请注意,在这里,您始终使用接口类型,当您创建带有约束的通用接口/类时,您所做的只是缩小可以在您的类中使用的类型。
在您的Invalid
方法中,您发现的是使用IAssignable
对象并将其分配给T
对象,即使T is IAssignable
没有保修toAssign.AssignMe
是同一类型,因此您的错误。在我上面做的修改中,你松散了泛型,然后你使用的实际类型是IAssignable
,所以一切正常。
希望有所帮助