c# generics constructor type-inference

¿Por qué el constructor C#no puede inferir el tipo?



generics type-inference (5)

¿Por qué no se admite la inferencia de tipos para los constructores de la misma manera que para los métodos genéricos?

public class MyType<T> { private readonly T field; public MyType(T value) { field = value; } } var obj = new MyType(42); // why can''t type inference work out that I want a MyType<int>?

Aunque podrías sortear esto con una clase de fábrica,

public class MyTypeFactory { public static MyType<T> Create<T>(T value) { return new MyType<T>(value); } } var myObj = MyTypeFactory.Create(42);

¿Hay alguna razón práctica o filosófica por la cual el constructor no pueda soportar la inferencia de tipo?


¿Hay alguna razón filosófica por la cual el constructor no pueda soportar la inferencia de tipo?

No. Cuando tienes

new Foo(bar)

entonces podríamos identificar todos los tipos llamados Foo en alcance independientemente de arity genérico, y luego sobrecargar la resolución en cada uno usando un algoritmo de inferencia de tipo de método modificado. Entonces tendríamos que crear un algoritmo de ''calidad'' que determine cuál de los dos constructores aplicables en dos tipos que tienen el mismo nombre pero diferente aridad genérica es el mejor constructor. Para mantener la compatibilidad con versiones anteriores, un codificador de tipo no genérico siempre debe ganar.

¿Hay alguna razón práctica por la cual el constructor no puede soportar la inferencia de tipo?

Sí. Incluso si el beneficio de la función supera sus costos, que son considerables, eso no es suficiente para que se implemente una función. La característica no solo tiene que ser una ganancia neta, tiene que ser una gran ganancia neta en comparación con todas las otras características posibles en las que podríamos estar invirtiendo. También tiene que ser mejor que gastar ese tiempo y esfuerzo en la corrección de errores, el rendimiento trabajo, y otras áreas posibles que podríamos poner ese esfuerzo. E idealmente tiene que encajar bien con lo que sea el "tema" del lanzamiento.

Además, como nota correctamente, puede obtener los beneficios de esta función sin tener realmente la función en sí, utilizando un patrón de fábrica. La existencia de soluciones alternativas hace que sea menos probable que alguna característica se implemente.

Esta característica ha estado en la lista de características posibles desde hace mucho tiempo. Nunca ha estado lo suficientemente cerca de la lista como para implementarse realmente.

ACTUALIZACIÓN de marzo de 2015

La característica propuesta lo hizo lo suficientemente cerca de la parte superior de la lista para que C # 6 sea especificado y diseñado, pero luego se cortó.


Aunque esto se ha respondido muchas veces antes, creo que necesito aclarar una cosa: C # admite la inferencia de tipo genérico en los constructores. El problema es que no admite añadir parámetros genéricos a los constructores ni escribir inferencias genéricas de tipo. Querer inferir el argumento de tipo genérico del tipo en sí mismo es básicamente lo mismo que requerir que Foo.Bar(0) infiera a Foo<int>.Bar(0) .


El constructor necesita tener la misma especificación genérica que la clase misma. De lo contrario, sería imposible saber si el int en su ejemplo se relacionaría con la clase o con el constructor.

var obj = new MyType<int>(42);

¿Sería eso la clase MyType<T> con el constructor MyType(int) o la clase MyType con el constructor MyType<T>(T) ?


La razón principal por la cual la inferencia de tipo genérico no puede funcionar en los constructores que desee es porque la clase "MyType" ni siquiera existe cuando todo lo que ha declarado es "MyType <T>". Recuerde que es legal tener ambos:

public class MyType<T> { }

y

public class MyType { }

Ambos serían legales. ¿Cómo eliminarías la ambigüedad de tu sintaxis si de hecho declararas ambas y las dos declararan un constructor conflictivo?


public class MyType<T> { private readonly T field; public MyType(T value) { field = value; } }

pueden, no hay necesidad de decirle al constructor ''qué es T'' de nuevo, dado que ya lo han hecho en la declinación de clase.

también su fábrica es incorrecta, necesita tener public class MyTypeFactory<T> no solo public class MyTypeFactory - a menos que declare la fábrica dentro de la clase MyType

Editar para actualizar:

Bueno, ¿es 42 un largo, un corto, un int, o algo más?

Digamos que tienes lo siguiente

class Base { public virtual void DoStuff() { Console.WriteLine("Base"); } } class Foo : Base { public override void DoStuff() { Console.WriteLine("Foo"); } }

Entonces hiciste esto

var c = new Foo(); var myType = new MyType(c);

¿Esperarías que se usara foo , o base ? Necesitamos decirle al compilador qué usar en lugar de T

Cuando realmente quería en base tipo

Por lo tanto, la

var myType = new MyType<Base>(c);