Typ musi być typem odniesienia, aby można go było używać jako parametru „T” w typie lub metodzie ogólnej

211

Zagłębiam się w generyczne i teraz mam sytuację, w której potrzebuję pomocy. Otrzymuję błąd kompilacji w poniższej klasie „Derived”, jak pokazano w tytule tematu. Widzę wiele innych postów podobnych do tego, ale nie widzę związku. Czy ktoś może mi powiedzieć, jak to rozwiązać?

using System;
using System.Collections.Generic;


namespace Example
{
    public class ViewContext
    {
        ViewContext() { }
    }

    public interface IModel
    {
    }

    public interface IView<T> where T : IModel 
    {
        ViewContext ViewContext { get; set; }
    }

    public class SomeModel : IModel
    {
        public SomeModel() { }
        public int ID { get; set; }
    }

    public class Base<T> where T : IModel
    {

        public Base(IView<T> view)
        {
        }
    }

    public class Derived<SomeModel> : Base<SomeModel> where SomeModel : IModel
    {

        public Derived(IView<SomeModel> view)
            : base(view)
        {
            SomeModel m = (SomeModel)Activator.CreateInstance(typeof(SomeModel));
            Service<SomeModel> s = new Service<SomeModel>();
            s.Work(m);
        }
    }

    public class Service<SomeModel> where SomeModel : IModel
    {
        public Service()
        {
        }

        public void Work(SomeModel m)
        {

        }
    }
}
ChrisS
źródło
Nie otrzymuję żadnych błędów kompilacji
Vince Panuccio,
Ten kod nie pokazuje tego błędu. Kompiluje się czysto.
Marc Gravell

Odpowiedzi:

474

Nie mogę repro, ale podejrzewam, że w twoim kodzie jest jakieś ograniczenie, które T : class- na przykład, musisz rozpropagować to, aby uszczęśliwić kompilator (trudno powiedzieć na pewno bez przykładu repro):

public class Derived<SomeModel> : Base<SomeModel> where SomeModel : class, IModel
                                                                    ^^^^^
                                                                 see this bit
Marc Gravell
źródło
12
Dziękuję, tak to jest to. Po dodaniu ograniczenia klasy błąd kompilacji zniknął. Poniższe wydaje się zaspokajać potrzebę typu refernce.
ChrisS,
oto co działa. klasa publiczna Baza <T> gdzie T: klasa, IModel {baza publiczna (IView <T> widok) {}} klasa publiczna Pochodna <SomeModel>: Baza <SomeModel> gdzie SomeModel: klasa, IModel {public Pochodna (IView <SomeModel> view): base (view) {SomeModel m = (SomeModel) Activator.CreateInstance (typeof (SomeModel)); Usługa <SomeModel> s = nowa usługa <SomeModel> (); s.Work (m); }}
ChrisS
Pomagał również :) Dzięki :) Na marginesie uważam, że nie powinniśmy kopiować tej samej konstelacji raz po raz, jeśli jest już zastosowana w interfejsie IMO.
Celdor
46

Ten błąd Tpojawia się, jeśli ograniczyłeś się do byciaclass

thekip
źródło
9

Jeśli nałożysz ograniczenia na ogólną klasę lub metodę, każda inna generyczna klasa lub metoda, która jej używa, musi mieć „co najmniej” te ograniczenia.

Guish
źródło