El tipo debe ser un tipo de referencia para usarlo como parámetro 'T' en el tipo o método genérico

211

Estoy profundizando en los genéricos y ahora tengo una situación en la que necesito ayuda. Recibo un error de compilación en la clase 'Derivada' a continuación, como se muestra en el título del tema. Veo muchas otras publicaciones similares a esta, pero no veo la relación. ¿Alguien puede decirme cómo resolver esto?

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
fuente
No recibo ningún error de compilación
Vince Panuccio
Este código no muestra ese error. Compila limpiamente.
Marc Gravell

Respuestas:

474

No puedo reprobar, pero sospecho que en su código real hay una restricción en algún lugar que T : classnecesita propagar para hacer feliz al compilador, por ejemplo (difícil de decir con certeza sin un ejemplo de repro):

public class Derived<SomeModel> : Base<SomeModel> where SomeModel : class, IModel
                                                                    ^^^^^
                                                                 see this bit
Marc Gravell
fuente
12
Gracias, sí, eso es. Una vez que agregué la restricción de clase, el error de compilación desapareció. Lo siguiente parece satisfacer la necesidad del tipo de referencia.
ChrisS
Esto es lo que funciona. public class Base <T> donde T: class, IModel {public Base (IView <T> view) {}} public class Derived <SomeModel>: Base <SomeModel> donde SomeModel: class, IModel {public Derived (IView <SomeModel> view): base (view) {SomeModel m = (SomeModel) Activator.CreateInstance (typeof (SomeModel)); Servicio <SomeModel> s = nuevo Servicio <SomeModel> (); s.Trabajo (m); }}
ChrisS
También ayudó :) Gracias :) Como nota al margen, creo que no deberíamos copiar la misma restricción una y otra vez si ya está aplicada en la interfaz, IMO.
Celdor el
46

Obtiene este error si se ha limitado Ta ser unclass

thekip
fuente
9

Si coloca restricciones en una clase o método genérico, cualquier otra clase o método genérico que lo esté utilizando debe tener "al menos" esas restricciones.

Guish
fuente