No se puede crear una instancia de la variable tipo de ‘Elemento’ porque no tienen la nueva() restricción

Estoy tratando de poner a prueba un método – y de obtener un error:

Puede crear una instancia de la variable tipo de ‘Elemento’ porque no tienen la nueva() restricción

De información necesarios por debajo:

public interface IHasRect
{
    Rectangle Rectangle { get; }
}

Clase auxiliar:

class Item : IHasRect
{
    public Item(Point p, int size)
    {
        m_size = size;
        m_rectangle = new Rectangle(p.X, p.Y, m_size, m_size); 
    }
}

Para que la función pueda ser probado, necesito crear una instancia de un objeto…

public class SomeClass<T> where T : IHasRect

La prueba:

public void CountTestHelper<Item>() where Item : IHasRect
{
    Rectangle rectangle = new Rectangle(0, 0, 100, 100); 
    SomeClass<Item> target = new SomeClass<Item>(rectangle);            
    Point p = new Point(10,10);
    Item i = new Item(p, 10);      //error here        
    ...
}
[TestMethod()]
public void CountTest()
{
    CountTestHelper<Item>();
}   

Estoy tratando de entender lo que significa este error, o cómo solucionarlo, por la lectura de http://msdn.microsoft.com/en-us/library/d5x73970.aspx y http://msdn.microsoft.com/en-us/library/x3y47hd4.aspx -, pero no ayuda.

No entiendo este error – ya he restringido el «SomeClass» de tipo. No puedo restringir toda clase de Prueba (la prueba de la unidad de la clase generada por Visual Studio, que contiene todas las pruebas) – voy a tener un número de otros errores de otra manera. La clase de Elemento no tiene ningún tipo de plantilla…

InformationsquelleAutor Thalia | 2013-02-04

3 Kommentare

  1. 13

    La Item en la línea:

    Item i = new Item(p, 10);

    se refiere al parámetro de tipo genérico Item de la CountTestHelper método, no de la clase Item. Cambiar el parámetro genérico nombre por ejemplo,

    public void CountTestHelper<TItem>() where TItem : IHasRect
    {
        Rectangle rectangle = new Rectangle(0, 0, 100, 100); 
        SomeClass<TItem> target = new SomeClass<TItem>(rectangle);            
        Point p = new Point(10,10);
        Item i = new Item(p, 10);    
        ...
    }

    alternativamente, usted puede calificar plenamente el nombre de la Item clase que desea crear:

    public void CountTestHelper<Item>() where Item : IHasRect
    {
        Rectangle rectangle = new Rectangle(0, 0, 100, 100); 
        SomeClass<Item> target = new SomeClass<Item>(rectangle);            
        Point p = new Point(10,10);
        SomeNamespace.Item i = new SomeNamespace.Item(p, 10);  
    }
    • Ustedes estaban viendo lo mismo que yo estaba. Me miró y fue como «Espera, el Punto es un parámetro de tipo no un tipo.
    • Esta respuesta es la correcta para la pregunta. Sin embargo, si usted vino aquí buscando una manera de crear una instancia de una propiedad con un tipo genérico, usted va a querer leer la respuesta de @MarcinJuraszek.
  2. 113

    Que no se puede inicializar el tipo Genérico de objetos, a menos que lo marca como de la aplicación de constructor predeterminado utilizando new palabras clave:

    public void CountTestHelper<Item>() where Item : IHasRect, new()
     {
        Rectangle rectangle = new Rectangle(0, 0, 100, 100); 
        SomeClass<Item> target = new SomeClass<Item>(rectangle);            
        Point p = new Point(10,10);
        Item i = new Item();    //constructor has to be parameterless!
        ...
     }

    Por otro lado, si usted está tratando de initializa Item tipo de objeto definido en otro lugar de la aplicación pruebe a utilizar el espacio de nombres antes:

    MyAppNamespace.Item i = new MyAppNamespace.Item(p, 10);
    • me pegaba a él, esta es la respuesta correcta +1
    • Excepto que sólo puede utilizar el constructor sin parámetros con new(). No entiendo por qué no han arreglado esto! edit: Ahh, te he editado mencionar que 😉
    • ‘Item’ debe ser un no-tipo abstracto con un público constructor sin parámetros con el fin de utilizarlo como parámetro ‘Item’ en el tipo genérico o método ‘CountTestHelper<Item>()’
    • También, tenga en cuenta la respuesta de Lee, asegúrese de que usted está familiarizado con los genéricos tipo de definiciones. Aquí, su «Elemento» de la clase NO es la clase definida anteriormente, es sólo un lugar, tipo soporte que usted está temporalmente llamando Elemento…
    • Existe una versión que permita que los nuevos(parámetro1, parámetro2, etc) para los genéricos de tipo T?
  3. 30

    Debido a que muchas personas obtener aquí la pregunta tilte (que es muy genérico y coincide con el mensaje del compilador) permítanme dar una respuesta más detallada acerca de la compilación de error itsef.

    Que son el uso de medicamentos genéricos en un método. El compilador no sabe qué tipo va a recibir y por lo tanto no se justifica que el tipo tiene un sin parámetros construtor. Por ejemplo:

    class A {
        A(int i){ ... }
    }
    
    class B { ... }
    
    public void MyMethod<T>(){
        T t = new T(); //This would be fine if you use 'MyMethod<B>' but you would have a problem calling 'MyMethod<A>' (because A doesn´t have a parameterless construtor;
    }

    Para resolver esto, usted puede decirle al compilador que su parámetro genérico tiene un sin parámetros construtor. Esto se hace mediante la definición de restricciones:

    public void MyMethod<T>()  where T: new(){
        T t = new T(); //Now it's ok because compiler will ensure that you only call generic method using a type with parameterless construtor;
    }

    Obtener más información acerca de constructor de las limitaciones que puede encontrar aquí:
    https://msdn.microsoft.com/en-us/library/bb384067.aspx

    • Gracias, esta era la respuesta correcta para mí!
    • Public Sub MyMethod(Of T As New)() es el equivalente de código VB, para los interesados. Más información disponible en MSDN.

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea