Definire attuazione facoltativa metodi di Interfaccia?

È possibile definire un’Interfaccia opzionale modalità di attuazione? Io per esempio ho il seguente definizione di interfaccia come IDataReader nella mia libreria di base:

public interface IDataReader<T> {
  void StartRead(T data);
  void Stop();
}

Tuttavia, nel mio attuale implementazioni, il metodo Stop() non è mai stato utilizzato o attuate. In tutte le mie classi di implementazione, questo metodo deve essere attuata con passi NotImplementedExcetion() come impostazione predefinita:

class MyDataReader : IDataReader<MyData> {
   ...
   public void Stop()
   {
     //this none implementaion looks like uncompleted codes
     throw NotImplementedException();
   }

Naturalmente, posso rimuovere il tiro codice di eccezione e lasciare vuoto.

Quando ho progettato questo lettore di dati, interfaccia, ho pensato che dovrebbe fornire un modo per interrompere il processo di lettura. Forse riusciremo ad utilizzare la funzione Stop() in futuro.

Comunque, non sono sicuro se è possibile rendere questo metodo Stop() come optional metodo di implementazione? L’unico modo che posso pensare è quello di definire due interfacce uno stop e l’altro senza, come IDataReader e IDataReader2. Un’altra opzione è quella di rompere questo uno per le interfacce come questo:

 interface IDataReader<T> {
    void StartRead(T data);
 }

 interface IStop {
    void Stop();
 }

Nel mio attuazione casi, devo cast o di usare come IStop per verificare se la mia implementazione supporta il metodo Stop ():

 reader.StartRead(myData);
 ....
 //some where when I need to stop reader
 IStop stoppable = reader as IStop;
 if (stoppable != null ) stoppable.Stop();
 ...

Ancora devo scrivere questi codici. Qualche suggerimento? Non sono sicuro se c’è qualche modo per definire attuazione facoltativa metodi di un’interfaccia .Net o C#?

 

6 Replies
  1. 6

    Per info, un altro approccio abbastanza comune nel BCL è Supports* sulla stessa interfaccia, cioè

    bool SupportsStop {get;}
    void Stop();

    (esempi di questo, per esempio, in IBindingList).

    Io non sono finta che sia “puro” o altro, ma funziona – ma significa che ora avete due metodi da implementare per la funzionalità, non uno. Interfacce Separate (IStoppableReader, per esempio) potrebbe essere preferibile.

    Per info, se l’implementazione è comune tra tutti implementazioni, quindi è possibile utilizzare i metodi di estensione; per un banale esempio:

    public static void AddRange<T>(this IList<T> list, IEnumerable<T> items) {
        foreach(T item in items) list.Add(item);
    }

    (o l’equivalente per l’interfaccia). Se si fornire una versione specializzata contro il cemento tipo, quindi avrà la precedenza (ma solo se il chiamante si sa circa la variabile come tipo concreto, non l’interfaccia). Quindi, con quanto sopra, chiunque consapevolmente utilizzando un List<T> utilizza ancora List<T>‘s versione di AddRange; ma se ha una List<T> ma solo sapere come IList<T>, viene utilizzato il metodo di estensione.

  2. 7

    Interessanti. Dovrò citare qui:

    Tuttavia, nel mio attuale
    implementazioni, il metodo Stop() ha
    mai stato usato o implementato. In tutti
    le mie classi di implementazione, questo metodo
    deve essere attuata con passi
    NotImplementedExcetion() come impostazione predefinita:

    Se questo è il caso, allora si hanno due opzioni:

    1. Rimuovere il metodo Stop() dell’interfaccia. Se non è utilizzato da ogni implementatore di interfaccia, è chiaramente non ci appartengono.
      • Invece di un’interfaccia, è possibile convertire l’interfaccia di una classe base astratta. In questo modo non è necessario eseguire l’override di un vuoto metodo Stop() fino a quando è necessario.

    Aggiornamento L’unico modo penso che i metodi possono essere facoltativa è quello di assegnare un metodo di una variabile (di tipo delegato simili a firma del metodo) e poi valutare se il metodo è null prima di chiamare ovunque.

    Questo di solito è fatto per i gestori di eventi, in cui il conduttore può o non può essere presente, e può essere considerato facoltativo.

    • Vedo il tuo punto. Effettivamente ho rimosso il metodo. Questo è il mio controllo. Tuttavia, dopo che ho fatto, ho cercato di scoprire se c’è un modo per rendere il metodo di opzioni .Net? Mi piace tenerlo lì come opzionale nel caso in cui mi devo fermare il processo attraverso l’interfaccia.
    • Io aggiornare la mia risposta re: facoltativa metodi.
  3. 5

    Se il metodo è appropriato per il vostro attuazione, gettare InvalidOperationException come la maggior parte di iteratori fare quando si chiama Reset su di loro. Un’alternativa è NotSupportedException che tende ad essere utilizzato da System.IO. Quest’ultimo è più logico (come ha nulla a che fare con l’attuale stato dell’oggetto, ma solo la sua di cemento tipo), ma il primo è più comunemente usato nella mia esperienza.

    Tuttavia, è meglio mettere le cose in un’interfaccia quando hai veramente bisogno di loro – se si è ancora in una posizione dove si può rimuovere Stop, io farei così se fossi in te.

    Non c’è il supporto unificato per l’interfaccia opzionale membri nella lingua o CLR.

    • C’è il Sistema.NotSupportedException in .NET 😉
    • d’accordo. Sembra che l’implementazione opzionale non è supportato in C#. Ho molti casi di attuare .Net core interfacce con metodi non utilizzato.
    • È vero. E ‘un po’ di confusione, avendo entrambi – io modificare la mia risposta.
  4. 4

    Se no classi nel codice implementare effettivamente Stop(), e non hai definitiva prevede di farlo in futuro, quindi non avete bisogno nella vostra interfaccia. Altrimenti, se alcuni ma non tutti di oggetti “con arresto”, quindi l’approccio corretto è infatti quello di rendere un’interfaccia separata come IStoppable, e i client devono quindi la query per esso come necessario.

  5. 0

    Se l’implementazione non implementa il metodo di interfaccia di Stop, poi si rompe obviousily il contratto che viene fornito con l’interfaccia. O si implementa il metodo Stop in modo appropriato (non da lancio di un’Eccezione e non lasciando vuota) o hai bisogno di una riprogettazione dell’interfaccia (per modo di modificare il contratto).

    Migliori Saluti

  6. 0

    C# versione 4 (o pagina relativa ai) è, considerando l’implementazione predefinita per le interfacce – ho sentito dire che sul channel9 un paio di mesi fa ;).

    Interfacce con l’implementazione di default si sarebbero comportati un po ‘ come classi base astratte. Ora che si può ereditare da più interfacce questo potrebbe significare che C# potrebbe ottenere l’ereditarietà multipla in forma di interfacce e implementazioni di default.

    Fino ad allora si potrebbe ottenere via con metodi di estensione…

    O il tipo di usufruire dei delegati.

    interface IOptionalStop
    {
        Action Stop { get; }
    }
    
    public class WithStop : IOptionalStop
    {
        #region IOptionalStop Members
    
        public Action Stop
        {
            get;
            private set;
        }
    
        #endregion
    
        public WithStop()
        {
            this.Stop =
                delegate
                {
                    //we are going to stop, honest!
                };
        }
    }
    
    public class WithoutStop : IOptionalStop
    {
        #region IOptionalStop Members
    
        public Action Stop
        {
            get;
            private set;
        }
    
        #endregion
    }
    
    
    public class Program
    {
        public static string Text { get; set; }
    
    
        public static void Main(string[] args)
        {
            var a = new WithStop();
    
            a.Stop();
    
            var o = new WithoutStop();
    
            //Stop is null and we cannot actually call it
            a.Stop();
    
        }
    }
    • Non c’è “l’implementazione predefinita per” interfacce in C# 4.0.
    • Troppo triste. Credo che questo dovrebbe essere molto facile da fare. Basta aggiungere una nuova chiave di direttiva del lavoro Opzionale prima di un metodi .net compilatore genererà corpo vuoto codici per questo metodo. Chiamare questo metodo opzionale, se non attuate, non fa nulla e non fa eccezione. Naturalmente, questo può aprire una porta per le persone a gettare in troppi cattivi interfacce. C’è un valore di implementazione opzionale, ma può essere abusato. Solo il mio commento.
    • Vedo alcuni errori di battitura. Ci scusiamo per questo. Non è troppo tardi in Canada adesso.
    • Che cosa circa il delegato approccio nell’esempio che ho avuto dato che funziona con la versione corrente di c#?
    • Mi piace. Ho pensato di delegare, ma non è così pulita come la tua. Tuttavia, ancora devo controllare se il delegato è nullo o non e definire un altro delegato per l’attuazione.
    • Si potrebbe creare un exteinsion metodo .InvokeSafe() per ignorare se il target delegato è null…

Lascia un commento