2010-09-15 10 views
5

Non credo sia possibile, ma qui ...Generici C#: è possibile creare un metodo con n Tipi generici ...?

Voglio aggiungere un metodo che possa gestire n numeri di generici. per esempio:

bool<T> MyMethod() where T: Isomething 
{ 
} 

lavorerà per un tipo

bool<T,K> MyMethod() where T: Isomething 
{ 
} 

lavorerà per due tipi

C'è un modo per lavorare con i tipi n - per esempio

bool<T[]> MyMethod() where T: Isomething 
{ 
} 

il motivo che voglio fare questo è quello di implementare un metodo di supporto NHibernate statica che può caricare da più assembly - proprio ora funziona benissimo per un assemblaggio. Il mio metodo attuale è come illustrato di seguito:

 public static ISessionFactory GetMySqlSessionFactory<T>(string connectionString, bool BuildSchema) 
    { 
     //configuring is meant to be costly so just do it once for each db and store statically 
     if (!AllFactories.ContainsKey(connectionString)) 
     { 
      var configuration = 
      Fluently.Configure() 
      .Database(MySQLConfiguration.Standard 
         .ConnectionString(connectionString) 
         .ShowSql() //for development/debug only.. 
         .UseOuterJoin() 
         .QuerySubstitutions("true 1, false 0, yes 'Y', no 'N'")) 
      .Mappings(m => 
         { 
          m.FluentMappings.AddFromAssemblyOf<T>(); 
          m.AutoMappings.Add(AutoMap.AssemblyOf<T>().Conventions.Add<CascadeAll>); 
         }) 
      .ExposeConfiguration(cfg => 
           { 
            new SchemaExport(cfg) 
            .Create(BuildSchema, BuildSchema); 
           }); 
      AllFactories[connectionString] = configuration.BuildSessionFactory(); 
     } 

     return AllFactories[connectionString]; 
    } 

dove la linea: m.FluentMappings.AddFromAssemblyOf(), vorrei aggiungere più tipi di esempio

foreach(T in T[]){ 
    m.FluentMappings.AddFromAssemblyOf<T>() 

}

Ovviamente questo non potrebbe funzionare non sono completamente muto, ma io non sono così caldo sui farmaci generici - qualcuno può confermare che questo non è possibile :-) ..? Quale sarebbe il modo più elegante per raggiungere questo effetto secondo te ..?

+1

Come nota Jon, questa non è una funzionalità di C# o del sistema di tipo CLR. Se questo tipo di sistema ti interessa, considera la possibilità di leggere su tipi di rango superiore in Haskell. –

+0

@Eric - grazie - Ho appena iniziato a guardare Haskell e sembra una lingua molto interessante. –

risposta

6

No - l'arità di tipi e metodi generici è fissata su una base per tipo/metodo.

Ecco perché ci sono tutti i diversi tipi Action<...>, e Tuple<...> nel framework.

Di tanto in tanto, che è un peccato, ma si ottiene nel modo relativamente raramente, e ho il sospetto ogni genere di cose sarebbe molto più complicato con arity variabile.

+0

Grazie - questa è una risposta - cioè che non è possibile, ma hai qualche suggerimento su come potrebbe essere fatto - c'è qualcosa con riflessioni, ecc. Che può essere usato per scorrere un elenco di tipi e creare un generico basato su loro? per esempio. passando i tipi come array? Ho quasi sentito di darti un segno corretto per insegnarmi una nuova parola. Ora proverò a far cadere arity in quante più frasi possibili. –

+0

@Mark: Sospetto che la tua migliore opzione al momento sia semplicemente quella di sovraccaricare il metodo. (Puoi sovraccaricare per arity.) In alternativa, fai in modo che il metodo restituisca qualcosa di diverso da 'bool', in modo che tu possa chiamarlo più volte in maniera concatenata/fluente. –

+0

grazie - non mi è mai venuto in mente di parlare fluentemente - questo è esattamente quello che farò! qualcosa come NHelper (ConnectionString). Da (). Da (). Build() - superbo! –

1

sembra che tu abbia ripetuto lo stesso errore che Newton aveva fatto una volta. Ha due gatti uno era più grande e l'altro era più piccolo. Ha fatto due fori nella porta, un buco più grande per quello più grande e uno più piccolo per il gatto più piccolo. Dove, in realtà, aveva bisogno di un grande buco per assistere entrambi i gatti.

Perché non creare un unico metodo in grado di affrontare con ben tipi che si desidera ..

bool<T[]> MyMethod() where T: Isomething 
{ 
} 
+0

Grazie ma non sono sicuro di aver letto correttamente la domanda. Non stavo creando 3 metodi diversi - solo cercando di illustrare un punto. il terzo non è valido, ma è il tipo di cosa che devo fare. –

0

Come altri hanno specificato non si può fare:

bool MyMethod<T[]>() where T: ISomething 

ma si può fare:

bool MyMethod<T>(params T[] somethings) where T : ISomething 

Per esempio:

public interface ISomething { string Name { get; set; } } 

public class SomethingA : ISomething { public string Name { get; set; } = nameof(SomethingA); } 
public class SomethingB : ISomething { public string Name { get; set; } = nameof(SomethingB); } 

void MyMethod<T>(params T[] somethings) where T : ISomething 
{ 
    foreach (var something in somethings) 
    { 
     if (something != null) 
      Console.WriteLine(something); 
    } 
} 

// Use it! 
ISomething a = new SomethingA(); 
ISomething b = new SomethingB(); 

// You don't need to specify the type in this call since it can determine it itself. 
MyMethod(a, b); 

// If calling it like this though you do: 
MyMethod<ISomething>(new SomethingA(), new SomethingB()); 

C# Interactive finestra di output:

> MyMethod(a, b); 
Submission#0+SomethingA 
Submission#0+SomethingB 
> 
> MyMethod<ISomething>(new SomethingA(), new SomethingB()); 
Submission#0+SomethingA 
Submission#0+SomethingB 

Quindi, è possibile includere i tipi desiderati (conformi al generico) e visualizzarli in cascata e chiamare il codice come specificato. Potresti anche NON usare i generici e solo prendere in oggetto params [] qualcosa; ma raccomanderei fortemente digitandolo se puoi.

Se qualcuno lo vede, per favore fatemi sapere se sono lontano dalla base o ho frainteso la domanda ... Grazie!