H
Harold Howe
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
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