I can’t understand why this will not compile

I am trying to understand why the following will not compile. The compiler complains about the line where CreatePresenter tries to set the View property:

It is not possible to implicitly convert the type 'Sandbox.Program.MyView' to 'TView'.

I know that the context of the assignment does not make sense, this is more for illustration. Any help would be great!

interface IView { } class Presenter<T> where T : IView { public T View { get; set; } } class MyView : IView { } class MyPresenter : Presenter<MyView> { public MyPresenter() { } } class ViewBase<TPresenter, TView> where TPresenter : Presenter<TView>, new() where TView : IView { public TPresenter Presenter { get; private set; } void CreatePresenter() { this.Presenter = new TPresenter(); this.Presenter.View = new MyView(); } } 
+4
source share
3 answers

In line:

 this.Presenter.View = new MyView(); 

You are trying to set the MyView object to a property of the general type TView (implementation of IView ).

This is not true because MyView is different from TView , so it cannot be assigned.

EDIT:

To expand a bit ...

You can assign a type to your interface, for example.

 IView v = new MyView(); // OK ! 

but you cannot assign an interface to one of your performers, for example:

 IView v = ...; MyView myView = v; // WRONG ! 

Here you are doing something more confusing, something like this:

  IView _______|_______ | | | | TView <-- MyView 

This is clearly wrong.
In fact, even if TView and MyView implement the same interface to allow this TView inherit from MyView , but not specified in the general restrictions, and therefore the compiler cannot make any assumptions.

See also davy8 answer for a clear example :)

+7
source

Imagine you have 2 more classes:

 class MyView2 : IView { } class MyPresenter2 : Presenter<MyView2> { public MyPresenter2() { } } 

Then you try to create a new ViewBase with these:

 var viewBase = new ViewBase<MyPresenter2, MyView2>(); 

In this case, in your method:

 void CreatePresenter() { this.Presenter = new TPresenter(); this.Presenter.View = new MyView(); } 

this.Presenter.View MyView2 , which does not inherit from MyView , although both of them implement IView

+1
source

MyView not guaranteed the same type of TView . You can have several MyViews implementations that are not MyViews using this generic class.

If you change the ViewBase to the code below, it will at least be compiled. I'm not sure how this will affect the behavior of your application.

 class ViewBase<TPresenter, TView> where TPresenter : Presenter<TView>, new() where TView : IView, new() { public TPresenter Presenter { get; private set; } void CreatePresenter() { this.Presenter = new TPresenter(); this.Presenter.View = new TView(); } } 
0
source

Source: https://habr.com/ru/post/1341880/


All Articles