How to design around type covariance error
How to correct this design. Error because C# doesn't allow Type Covariance. How can I improve or correct this design
public interface ITimeEvent
{
}
public interface IJobTimeEvent : ITimeEvent
{
}
public interface IActivityTimeEvent : ITimeEvent
{
}
public interface IAssignmentTimeEvent<T> where T : ITimeEvent
{
T ParentTimeEvent
{
get;
set;
}
}
public class ScheduleJobTimeEvent : IAssignmentTimeEvent<IJobTimeEvent>
{
public IJobTimeEvent ParentTimeEvent
{
get;
set;
}
}
public class ScheduleActivityTimeEvent : IAssignmentTimeEvent<IActivityTimeE开发者_高级运维vent>
{
public IActivityTimeEvent ParentTimeEvent
{
get;
set;
}
}
List<IAssignmentTimeEvent<ITimeEvent>> lst = new List<IAssignmentTimeEvent<ITimeEvent>>();
lst.Add(new ScheduleJobTimeEvent()); //Error because C# doesn't allow Type Covariance
lst.Add(new ScheduleActivityTimeEvent()); //Error because C# doesn't allow Type Covariance
C#4.0 and .net4.0 do allow either covariance or contravariance on generic parameters (on interfaces). See: http://msdn.microsoft.com/en-us/library/dd799517.aspx
You can make this work in C# 4.0, although you need to add the covariance specifier to the interface type parameter.
However, for this to work at all, you must guarantee that the type parameter will only be used in method call results (and not parameters), which means surrendering your interface property setter. Whether or not this is acceptable for the overall design is your call.
public interface IAssignmentTimeEvent<out T> where T : ITimeEvent
{
T ParentTimeEvent
{
get;
}
}
Could you use your common interface?
// usage...
var lst = new List<IAssignmentTimeEvent>();
// extended details...
var event2 = new ScheduleActivityTimeEvent();
var byInterface = (IAssignmentTimeEvent)event2;
byInterface.ParentTimeEvent = new ActivityTimeEvent(); //this works
byInterface.ParentTimeEvent = new JobTimeEvent(); //this throws
// new interface
public interface IAssignmentTimeEvent
{
ITimeEvent ParentTimeEvent { get; set; }
}
public interface IAssignmentTimeEvent<T> : IAssignmentTimeEvent
where T : ITimeEvent
{
new T ParentTimeEvent { get; set; }
}
public class ScheduleJobTimeEvent :
IAssignmentTimeEvent<IJobTimeEvent>
{
public IJobTimeEvent ParentTimeEvent { get; set; }
ITimeEvent IAssignmentTimeEvent.ParentTimeEvent
{
get { return ParentTimeEvent; }
set
{
if (!(value is IJobTimeEvent))
throw new InvalidCastException();
ParentTimeEvent = value as IJobTimeEvent;
}
}
}
public class ScheduleActivityTimeEvent :
IAssignmentTimeEvent<IActivityTimeEvent>
{
public IActivityTimeEvent ParentTimeEvent { get; set; }
ITimeEvent IAssignmentTimeEvent.ParentTimeEvent
{
get { return ParentTimeEvent; }
set
{
if (!(value is IActivityTimeEvent))
throw new InvalidCastException();
ParentTimeEvent = value as IActivityTimeEvent;
}
}
}
精彩评论