Pregunta

Supongo que esto es más de un público despotricar, pero ¿por qué no puedo obtener c# para inferir mi Id tipo?

public EntityT Get<EntityT>(IdT id) where EntityT : EntityObject<IdT>

y un definido EntityObject con un Guid como un Id de la siguiente manera:

public Foo : EntityObject<Guid>

La herencia de la abstracta EntityObject clase definida de la siguiente manera:

public abstract class EntityObject<IdT>
{
    public IdT id { get; set; }
}

El uso del método get sería como sigue:

IRepository repository = new Repository();
var hydratedFoo = repository.Get<Foo>(someGuidId);

editado para proporcionar más aclaraciones.

¿Fue útil?

Solución

Es difícil de decir, dado que sólo ha dado dos declaraciones, no la estés usando.Es IdT otro parámetro de tipo en algún lugar?(Si se TId, que sugeriría es - pero el hecho de que usted está usando EntityT para otro tipo de parámetros, contrario a los convenios, sugiere que tal vez IdT es así...)

Ahora, suponiendo que IdT es en realidad Guid en su caso, cómo debe ser la del compilador de trabajo que quieres decir Foo?Podría haber otros tipos de derivados de EntityObject<Guid>.

En resumen, que no nos han dado suficiente información para decir nada seguro, pero suena como que usted está básicamente haciendo exigencias irrazonables en el compilador.

EDITAR:Bueno, aquí está mi conjetura en cuanto a lo que tiene, el uso normal de las convenciones de nomenclatura:

public interface IRepository
{
    TEntity Get<TEntity, TId>(TId id) where TEntity : EntityObject<TId>
}

public abstract class EntityObject<TId>
{
    public IdT id { get; set; }
}

public class Foo : EntityObject<Guid> {} 

Quieres hacer:

IRepository repository = GetRepositoryFromSomewhere();
Foo foo = repository.Get<Foo>(someGuid);

Mientras que en la actualidad tiene que hacer:

Foo foo = repository.Get<Foo, Guid>(someGuid);

Sí, el compilador es lo que es muy ligeramente más difícil de lo necesario.Conjunto de 6 caracteres adicionales, por el bien de mantener el idioma más simple y las reglas de inferencia de tipos más fáciles de entender.

Básicamente, el tipo de inferencia es a todo o nada el asunto - ya sea todos los parámetros de tipo que se infieren o ninguno de ellos.Que mantiene la sencillez ya que no es necesario para el trabajo de los que están especificados y los que no lo son.Eso es parte del problema, y la otra parte es que sólo se puede expresar restricciones en el tipo de los parámetros del método, no puede tener:

class Repository<TEntity>
{
    TEntity Get<TId>(TId id) where TEntity : EntityObject<TId>
}

debido a que la limitante TEntity, no TId.De nuevo, este tipo de cosas hace que la inferencia de tipo simple.

Ahora podría potencialmente escribir:

Foo foo = repository.Get(someGuid).For<Foo>();

con una adecuada Get método y una interfaz adicional.Creo que me gustaría, personalmente, prefiero utilizar Get<Foo, Guid> sin embargo.

Otros consejos

Una declaración como

public EntityT Get<EntityT>(IdT id) where EntityT : EntityObject<IdT>

exige que IdT es un tipo de hormigón. Si desea parametrizar IdT así, que había necesidad de utilizar

public EntityT Get<EntityT, IdT>(IdT id) where EntityT : EntityObject<IdT>

Pero eso no es probable que lo que se desea.

Esta es la razón por la que he casi renunciado a tipos genéricos clave con entidades genéricas. No podía encontrar la manera de conseguir mis entidades tener tipos clave genéricas y sin rociar los dos por todo el lugar. Ahora me he decidido por claves enteras (que es lo que tengo todas partes de todos modos) pero se siente mal.

Si su firma del método era la siguiente:

public TEntity Get<TEntity, TId>(TId id) where TEntity : EntityObject<TId>

El compilador tendría algo con qué trabajar ...

A continuación, llama a conseguir con algo como:

Edit (me equivoqué): Producto p = Get (id);

Product p = Get<Product, Guid>(id);

clavada esta respuesta de Jon con su puesto encima de la tapa por lo que callo y rastrear de nuevo en mi agujero.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top