By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
432,046 Members | 2,105 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 432,046 IT Pros & Developers. It's quick & easy.

Generic constraints: compiler errors on conversion that should bevalid

P: n/a
Howdy all,

I am getting a compiler error regarding a consrained conversion. It
complains that it can't make the type conversion, even though the
generic type argument inherits from the target of the conversion. I have
trimmed my source down as much as possible.

The classes implement something that behaves sort of like the Mediator
design pattern, but where the colleagues are abstract, and can be added
or removed on the fly. I guess that makes this more like the Observer
pattern. Either way, the base classes are designed to handle the plumbing.

The idea is that there is a mediator object that contains a list of view
objects. When something of interest happens in the mediator, it notifies
the views.

// main.cs
using System;
using System.Collections.Generic;

//---------------------------------------
// base types to handle plumbing
public interface IMediator<TView> //: IList<T>
{
// In reality, this interface inherits from IList<T>, but
// I removed that inheritance for brevity.
void Add(TView item);
void Clear();
}

public interface IBaseView<TMediator, TView>
where TMediator : IMediator<TView>
{
// All views have a Mediator property.
TMediator Mediator { get;set;}
}

public class BaseView<TMediator, TView> : IBaseView<TMediator, TView>
where TMediator : IMediator<TView>
{
public BaseView() {}

public TMediator Mediator
{
get { return m_Mediator; }
set { m_Mediator = value; }
}

protected TMediator m_Mediator;
}
public class Mediator<T> : IMediator<T>
where T : IBaseView<Mediator<T>, T>
{
protected List<T> m_List = new List<T>();

public virtual void Add(T item)
{
m_List.Add(item);
item.Mediator = this;
}
public virtual void Clear()
{
foreach(T t in m_List)
t.Mediator = null;
m_List.Clear();
}
}

//---------------------------------------
// concrete types
public interface IView : IBaseView<Mediator, IView>
{
void ZoomChanged();
}

public class ConcreteView : BaseView<Mediator, IView>, IView
{
public virtual void ZoomChanged() {}
}

public class Mediator : Mediator<IView> // ERROR on this line
{
public void ZoomTo(float zoom)
{
// ... zoom the display
foreach(IView view in m_List)
view.ZoomChanged();
}
}

class Program
{
static void Main(string[] args)
{
Mediator med = new Mediator();
med.Add(new ConcreteView());

med.ZoomTo(.5f);
}
}

// compiler error
Error 1 The type 'IView' must be convertible to
'IBaseView<Mediator<IView>,IView>' in order to use it as parameter 'T'
in the generic type or method 'Mediator<T>'

The confusing thing is that IView inherits from
IBaseView<Mediator<IView>, IView>, so I don't understand why the
compiler complains about the conversion.

H^2
Feb 27 '06 #1
Share this Question
Share on Google+
2 Replies


P: n/a
Harold Howe <hh***@gowebway.com> writes:
Howdy all,

I am getting a compiler error regarding a consrained conversion. It
complains that it can't make the type conversion, even though the
generic type argument inherits from the target of the conversion. I
have trimmed my source down as much as possible.

The classes implement something that behaves sort of like the Mediator
design pattern, but where the colleagues are abstract, and can be
added or removed on the fly. I guess that makes this more like the
Observer pattern. Either way, the base classes are designed to handle
the plumbing.

The idea is that there is a mediator object that contains a list of
view objects. When something of interest happens in the mediator, it
notifies the views.

// main.cs
using System;
using System.Collections.Generic;

//---------------------------------------
// base types to handle plumbing
public interface IMediator<TView> //: IList<T>
{
// In reality, this interface inherits from IList<T>, but
// I removed that inheritance for brevity.
void Add(TView item);
void Clear();
}

public interface IBaseView<TMediator, TView>
where TMediator : IMediator<TView>
{
// All views have a Mediator property.
TMediator Mediator { get;set;}
}

public class BaseView<TMediator, TView> : IBaseView<TMediator, TView>
where TMediator : IMediator<TView>
{
public BaseView() {}

public TMediator Mediator
{
get { return m_Mediator; }
set { m_Mediator = value; }
}

protected TMediator m_Mediator;
}
public class Mediator<T> : IMediator<T>
where T : IBaseView<Mediator<T>, T>
{
protected List<T> m_List = new List<T>();

public virtual void Add(T item)
{
m_List.Add(item);
item.Mediator = this;
}
public virtual void Clear()
{
foreach(T t in m_List)
t.Mediator = null;
m_List.Clear();
}
}

//---------------------------------------
// concrete types
public interface IView : IBaseView<Mediator, IView>
{
void ZoomChanged();
}

public class ConcreteView : BaseView<Mediator, IView>, IView
{
public virtual void ZoomChanged() {}
}

public class Mediator : Mediator<IView> // ERROR on this line
{
public void ZoomTo(float zoom)
{
// ... zoom the display
foreach(IView view in m_List)
view.ZoomChanged();
}
}

class Program
{
static void Main(string[] args)
{
Mediator med = new Mediator();
med.Add(new ConcreteView());

med.ZoomTo(.5f);
}
}

// compiler error
Error 1 The type 'IView' must be convertible to
'IBaseView<Mediator<IView>,IView>' in order to use it as parameter 'T'
in the generic type or method 'Mediator<T>'

The confusing thing is that IView inherits from
IBaseView<Mediator<IView>, IView>, so I don't understand why the
compiler complains about the conversion.


Generic types are not co-variant in their generic parameters, so
from

IView : IBaseView<Mediator, IView>
Mediator : Mediator<IView>

it does not follow that

IView : IBaseView<Mediator<IView>, IView>

Peter
--
Department of Natural Sciences http://www.dina.kvl.dk/~sestoft/
Royal Veterinary and Agricultural University * Tel +45 3528 2334
Thorvaldsensvej 40, DK-1871 Frederiksberg C, Denmark * Fax +45 3528 2350
Feb 27 '06 #2

P: n/a
Generic types are not co-variant in their generic parameters, so
from


Ok. Thanks for the response.

H^2
Mar 10 '06 #3

This discussion thread is closed

Replies have been disabled for this discussion.