C# .NET MVC 5 DisplayTemplate dla IListy interfejsów.

Odpowiedz Nowy wątek
2018-11-23 17:33
0

Drodzy Koledzy,
przede wszystkim pragnę się powitać, bo to mój pierwszy post :)

Problem mam następujący - mam interfejs, klasę implementującą interfejs oraz klasę dziedziczącą klasę implementującą interfejs. Wygląda to tak:

public class SlownikBazowyVm : ISlownikBazowy
    {
        public int? Id { get; set; }
        public string Wartosc { get; set; }
        public bool Aktywny { get; set; }
        public int? Kolejnosc { get; set; }
    }

    public interface ISlownikBazowy
    {
        int? Id { get; set; }

        string Wartosc { get; set; }

        bool Aktywny { get; set; }

        int? Kolejnosc { get; set; }
    }

    public class SlownikSzczegolowyVm : SlownikBazowyVm
    {

    }

Chcę przygotować display template do takiego pola: IList<slownikszczegolowyvm>. W display template mam zdefiniowany model: @model IList<islownikbazowy>
Nad polem mam podanego UIHinta do odpowiedniego pliku .cshtml. Jednak próba wykonania tego kodu kończy się wyjątkiem: "The model item passed into the dictionary is of type 'System.Collections.Generic.List1[SlownikSzczegolowyVm]', but this dictionary requires a model item of type 'System.Collections.Generic.IList1[ISlownikBazowy]'.".
Gdyby nie była to lista to zadziałałoby poprawnie, co właśnie sprawdziłem. Nie rozumiem jednak dlaczego program rzuca wyjątkiem skoro podaję do displaytemplate obiekt implementujący interfejs.
Z góry dziękuję za wskazówki i pozdrawiam.

PS: Mam nadzieję, że formatowanie jest ok, podpierałem się instrukcją: Formatowanie treści postów na forum

edytowany 4x, ostatnio: dawid75_75, 2018-11-23 17:37

Pozostało 580 znaków

2018-11-23 17:50
2

Spróbuj użyć IEnumerable zamiast IList, IEnumerable jest kowariancyjne.


#Dżunior React Devloper wanna be#

Pozostało 580 znaków

2018-11-23 21:26
0

Rzeczywiście, działa prawidłowo. Nie rozumiem jednak dlaczego. Co to znaczy, że IEnumerable jest kowariancyjne?

edytowany 1x, ostatnio: dawid75_75, 2018-11-23 21:26

Pozostało 580 znaków

2018-11-23 21:45

Zobaczmy na definicję :
public interface IEnumerable< out T>
public interface IList<t>

w IEnumerable przed T masz słówko out, które mówi że typ jest kowariancyjny, czyli zamiast typu bazowego możesz użyć dowolny typ pochodny, w IList nie masz tego słówka out, więc T jest niezmienny/invariant.

Dlaczego IList nie jest kowariancyjny? Bo w przeciwieństwie do IEnumerable umożliwia dodawanie elementów i gdyby był kowariancyjny to by był problem:

class Gruszka dziedziczy po Owoc
class Sliwka dziedziczy po Owoc

var gruszki= new List<Gruszka>();
IList<Owoc> foo = gruszki;
foo.Add(new Sliwka());      // aaaaa tak nie wolno!

bo moglibyśmy dodać do listy "gruszek" elementy które nie są gruszkami :D

Jako ciekawostka tablice w C# są kowariancyjne, ale jest to błąd, skopiowany z Javy.


#Dżunior React Devloper wanna be#
edytowany 6x, ostatnio: neves, 2018-11-23 21:52

Pozostało 580 znaków

2018-11-23 22:01
0

No widzisz, nie wiedziałem o tym. Znalazłem też rozdział w dokumentacji na ten temat - jednak dopiero po tym jak wiedziałem czego szukać :D - https://docs.microsoft.com/pl[...]keywords/out-generic-modifier I dla dociekliwych link do artykułu o kowariancji i kontrawariancji: https://docs.microsoft.com/pl[...]variance-contravariance/index

Czy dobrze rozumiem, że w tym kontekście out oznacza zupełnie co innego niż out używane przy przekazywaniu parametrów funkcji przez referencję?

edytowany 1x, ostatnio: dawid75_75, 2018-11-23 22:02

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0