开发者

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;
        }
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜