Code:
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;
}
}
Problem:
In final example method _assignable
(which is T where T is IAssignable
) cannot be assigned the value toAssign.AssignMe
(which is of type IAssignable
), the compiler throws
"Cannot implicitly convert type 'IAssignable' to 'T'".
Why is this? T
is IAssignable
so surely an instance of IAssignable
can be assigned to it?
Why is this? T is IAssignable so surely an instance of IAssignable can be assigned to it?
Ah, no? T
is not IAssignable
, if it were, you would not need Generics. T
just implements IAssignable
.
Just because Button
and TextBox
inherit from Control
(or in a fictional example implement IControl
) does not mean you can assign a TextBox
to a Button
or vice versa.
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;
}
}