Domanda

Suppongo che questo è più di uno sproloquio pubblico, ma perché non posso ottenere C # di dedurre il tipo di mia Id?

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

e EntityObject definito con un GUID come Id come segue:

public Foo : EntityObject<Guid>

che eredita dalla classe astratta EntityObject definito come segue:

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

L'utilizzo del metodo get sarebbe la seguente:

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

a cura di fornire ulteriori chiarimenti.

È stato utile?

Soluzione

E 'difficile da dire, dato che hai dato solo due dichiarazioni, non come si sta utilizzando loro. IDT è un altro parametro tipo da qualche parte? (Se fosse TId, che sarebbe suggeriscono che è - ma il fatto che si sta utilizzando EntityT per un altro parametro di tipo, contrario alle convenzioni, suggerisce che forse IdT è così ...)

Ora, supponendo IdT è in realtà Guid nel tuo caso, come dovrebbe il compilatore di lavoro che si intende Foo? Ci potrebbero essere altri tipi derivanti da EntityObject<Guid>.

In breve, non avete ci ha dato informazioni sufficienti per dire nulla di certo, ma sembra che tu sei fondamentalmente richieste irragionevoli sul compilatore.

EDIT: Ok, ecco la mia ipotesi a quello che hai, utilizzando le normali convenzioni di denominazione:

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> {} 

Si vuole fare:

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

considerando che attualmente si deve fare:

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

Sì, il compilatore sta rendendo leggermente di più per voi di quanto necessario. Un intero 6 personaggi extra, per il bene di mantenere il linguaggio più semplice e le regole di inferenza di tipo più facile da capire.

In sostanza tipo inferenza è un tutto o niente vicenda - o tutti parametri di tipo vengono dedotti o nessuno di essi è. Che mantiene le cose semplici, come non c'è bisogno di capire quali sono stati specificati e quali non lo sono. Questo è parte del problema, e l'altra parte è che si può solo esprimere i vincoli sui parametri di tipo del metodo - non si può avere:

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

perché è vincolante TEntity, non TId. Ancora una volta, questo genere di cose fa inferenza di tipo più semplice.

Ora potrebbe potenzialmente scrivere:

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

con un metodo adeguato Get e un'interfaccia supplementare. Penso che mi piacerebbe personalmente preferisco utilizzare solo Get<Foo, Guid> però.

Altri suggerimenti

Una dichiarazione come

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

richiede che IDT è un tipo concreto. Se si vuole parametrizzare IDT così, avresti bisogno di usare

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

Ma che probabilmente non è quello che ci vuole.

Questo è il motivo per cui ho tutti ma rinunciato a tipi di chiave generici con soggetti generici. Non riuscivo a capire come ottenere i miei soggetti ad avere tipi di chiave generiche senza cospargendo i due in tutto il luogo. Ora ho optato per chiavi intere (che è quello che ho comunque dappertutto), ma ci si sente male.

Se la firma del metodo si presentava così:

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

Il compilatore avrebbe qualcosa con cui lavorare ...

È quindi chiamare ottenere con qualcosa del tipo:

EDIT (mi sbagliavo): prodotto p = Get (id);

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

di Jon inchiodato questa risposta con il suo posto sulla parte superiore quindi mi zitto e strisciare indietro nel mio buco.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top