Domanda

Ecco lo scenario mi trovo di fronte con:

public abstract class Record { }

public abstract class TableRecord : Record { }

public abstract class LookupTableRecord : TableRecord { }

public sealed class UserRecord : LookupTableRecord { }

public abstract class DataAccessLayer<TRecord> : IDataAccessLayer<TRecord>
    where TRecord : Record, new() { }

public abstract class TableDataAccessLayer<TTableRecord> : DataAccessLayer<TTableRecord>, ITableDataAccessLayer<TTableRecord>
    where TTableRecord : TableRecord, new() { }

public abstract class LookupTableDataAccessLayer<TLookupTableRecord> : TableDataAccessLayer<TLookupTableRecord>, ILookupTableDataAccessLayer<TLookupTableRecord>
    where TLookupTableRecord : LookupTableRecord, new() { }

public sealed class UserDataAccessLayer : LookupTableDataAccessLayer<UserRecord> { }

public interface IDataAccessLayer<TRecord>
    where TRecord : Record { }

public interface ITableDataAccessLayer<TTableRecord> : IDataAccessLayer<TTableRecord>
    where TTableRecord : TableRecord { }

public interface ILookupTableDataAccessLayer<TLookupTableRecord> : ITableDataAccessLayer<TLookupTableRecord>
    where TLookupTableRecord : LookupTableRecord { }

Ora, quando cerco di fare quanto segue cast, ma non viene compilato:

UserDataAccessLayer udal = new UserDataAccessLayer();
            ITableDataAccessLayer<TableRecord> itdal = (ITableDataAccessLayer<TableRecord>)udal;

Tuttavia, quando faccio il seguente fuso compila senza errori di runtime:

UserDataAccessLayer udal = new UserDataAccessLayer();
            ITableDataAccessLayer<UserRecord> itdal = (ITableDataAccessLayer<UserRecord>)udal;

ho davvero bisogno di lavorare con l'interfaccia di base ITableDataAccessLayer<TableRecord>, come io non conosco il tipo concreto.

Spero che questo è descrittivo e disponibile sufficiente a rispondere alla mia domanda.

È stato utile?

Soluzione

Che cosa si sta cercando di fare è supportato in .NET 4.0, ma non 3.5. Si chiama generico covarianza . Che cosa si può fare, invece, nel frattempo, è creare un'interfaccia non generica chiamata ITableDataAccessLayer (utilizzando il tipo di oggetto, ovunque usereste T) e di fornire implementazione esplicita. Questo è il numero tipi generici in .NET gestirlo.

Altri suggerimenti

In realtà, si vuole covarianza. punti di coppia.

In primo luogo, capire perché a volte questo deve essere illegale. Prendete per esempio IList. Supponiamo di avere un IList<Giraffe>, un elenco di giraffe. Si può convertire in una lista di animali? No, non è in sicurezza. Sì, un elenco di giraffe è una lista di animali, nel senso che ogni cosa nella lista è un animale. Ma le liste sono mutabili; si può attaccare una tigre in una lista di animali, ma se è davvero una lista di giraffe, allora questo deve fallire. Dal momento che non è sicuro, non ci sarà fare covariante IList in C # 4.

In secondo luogo, se questo argomento vi interessa, si potrebbe desiderare di leggere la mia lunga serie di articoli del blog su come la funzione è stata progettata per garantire la sicurezza di tipo.

http://blogs.msdn.com /ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx

In terzo luogo, FYI io sarà distacco le regole esatte che usiamo per calcolare quando un'interfaccia può tranquillamente covarianti o controvariante sul mio blog nel prossimo paio di settimane.

fa questo compilazione?

UserDataAccessLayer udal = new UserDataAccessLayer(); 
ITableDataAccessLayer<TTableRecord> itdal = (ITableDataAccessLayer<TTableRecord>)udal;

o anche solo

ITableDataAccessLayer<TTableRecord> itdal = new UserDataAccessLayer(); 

come è un'interfaccia generica, probabilmente ha bisogno di sapere che tipo è?

sarebbe utile conoscere il messaggio di errore troppo. che di solito mette in luce il soggetto.

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