I have an interface as follows:
public interface IPageViewModel<T> where T : class
{
string ViewName { get; set; }
T SelectedItem { get; set; }
List<T> ItemsList { get; set; }
}
Then, I have two classes:
internal class TestViewModel : IPageViewModel<INotifyPropertyChanged> //let's skip the fact that T is supposed to be a class while it somehow compiles and works with an interface...
internal class HardwareViewModel : IPageViewModel<Hardware>
Where Hardware
is:
public class Hardware : NotificationObject
And NotificationObject
is:
public class NotificationObject : INotifyPropertyChanged
And finally, I have a class as follows:
internal class NavigationViewModel
{
public List<IPageViewModel<INotifyPropertyChanged>> PageViewModelsList { get; set; } = new List<IPageViewModel<INotifyPropertyChanged>>();
public NavigationViewModel()
{
PageViewModelsList.Add(new TestViewModel());
PageViewModelsList.Add(new HardwareViewModel()); //error
}
}
Now, the problem is: while the first line in constructor compiles fine, the second one throws an error: cannot convert from ViewModels.HardwareViewModel to Helpers.IPageViewModel<System.Component.INotifyPropertyChanged>
.
But this makes no sense. Hardware
inherits from NotificationObject
which implements INotifyPropertyChanged
so IPageViewModel<Hardware>
=== IPageViewModel<INotifyPropertyChanged>
. Can anyone please explain why there's an error?
Thanks to the comments I've realized the topic causing these problems here is called 'variance'. So after reading a bit about it I decided to go with this solution:
public interface IPageViewModel
{
string ViewName { get; set; }
}
But if someone wanted to keep these fields and keep their interfaces covariant, it'd have to look something like this:
public interface IPageViewModel<out T> where T : class
{
string ViewName { get; set; }
T SelectedItem { get; }
IEnumerable<T> ItemsList { get; }
}