c# - Mixing Covariance and Contravariance -


goal:

iterate on following collection

var collection = new iimporttrigger<eventargs>[] {     new filesystemimporttrigger()     , new timerimporttrigger() }; 

in way

foreach (var trigger in collection) {     trigger.import += trigger.onimport; } 

this have far

public delegate void importtriggereventhandler<in t>(object sender, t args) t : eventargs;  public interface iimporttrigger<out t> t : eventargs {     event importtriggereventhandler<t> import;     void onimport<t1>(object sender, t1 args) t1 : eventargs; }  public class filesystemimporttrigger : iimporttrigger<filesystemeventargs> {     public event importtriggereventhandler<filesystemeventargs> import;      public void onimport<t>(object sender, t args) t : eventargs {  } }  public class timerimporttrigger : iimporttrigger<elapsedeventargs> {     public event importtriggereventhandler<elapsedeventargs> import;      public void onimport<t>(object sender, t args) t : eventargs {  } } 

expectations:

i define iimporttrigger 1 generic parameter.

problem:

if change interface definition following (notice generic argument t not covariant more).

public interface iimporttrigger<t> t : eventargs {     event importtriggereventhandler<t> import;     void onimport(object sender, t args); } 

and hence

public class filesystemimporttrigger : iimporttrigger<filesystemeventargs> {     public event importtriggereventhandler<filesystemeventargs> import;      public void onimport(object sender, filesystemeventargs args) { } }  public class timerimporttrigger : iimporttrigger<elapsedeventargs> {      public event importtriggereventhandler<elapsedeventargs> import;      public void onimport(object sender, elapsedeventargs args) { } } 

i wont able create common type collection

var collection = new iimporttrigger<eventargs>[] {     new filesystemimporttrigger()     , new timerimporttrigger() }; 

because generic parameter not output-safe more.

question:

is there way accomplish scenario?

by switching onimport not generic @ use explicit interface, make more derived interface not covariant has generic verson of onimport pull off.

internal class program {     private static void main(string[] args)     {         var collection = new iimporttriggerbase<eventargs>[]         {             new filesystemimporttrigger()             , new timerimporttrigger()         };          foreach (var trigger in collection)         {             trigger.import += trigger.onimport;         }     } }  public delegate void importtriggereventhandler<in t>(object sender, t args) t : eventargs;  public interface iimporttriggerbase<out t> t : eventargs {     event importtriggereventhandler<t> import;     void onimport(object sender, eventargs args); }  public interface iimporttrigger<t> : iimporttriggerbase<t> t : eventargs {     void onimport(object sender, t args); }  public class filesystemimporttrigger : iimporttrigger<filesystemeventargs> {     public event importtriggereventhandler<filesystemeventargs> import;      public void onimport(object sender, filesystemeventargs args) { }      void iimporttriggerbase<filesystemeventargs>.onimport(object sender, eventargs args)     {         onimport(sender, (filesystemeventargs)args);     } }  public class timerimporttrigger : iimporttrigger<elapsedeventargs> {     public event importtriggereventhandler<elapsedeventargs> import;      public void onimport(object sender, elapsedeventargs args) { }      void iimporttriggerbase<elapsedeventargs>.onimport(object sender, eventargs args)     {         onimport(sender, (elapsedeventargs)args);     } } 

however give cruft of onimport(object sender, eventargs args) method visible on iimporttrigger<t>.


that solve problem, if going , assuming correctly want derived classes able pick on fact import getting fired , not need onimport exposed

internal class program {     private static void main(string[] args)     {         var collection = new iimporttrigger<eventargs>[]         {             new filesystemimporttrigger()             , new timerimporttrigger()         };     } }  public delegate void importtriggereventhandler<in t>(object sender, t args) t : eventargs;  public interface iimporttrigger<out t> t : eventargs {     event importtriggereventhandler<t> import; }  public abstract class onimportbase<t> : iimporttrigger<t> t: eventargs {      public event importtriggereventhandler<t> import;      protected virtual void onimport(object sender, t args)     {         var tmp = import;         if (tmp != null)         {             tmp(this, args);         }     } }  public class filesystemimporttrigger : onimportbase<filesystemeventargs> {     protected override void onimport(object sender, filesystemeventargs args)     {         dosomeextrastuffbeforeimport();         base.onimport(sender, args);     }      private void dosomeextrastuffbeforeimport()     {     } }  public class timerimporttrigger : onimportbase<elapsedeventargs> {     protected override void onimport(object sender, elapsedeventargs args)     {         base.onimport(sender, args);         dosomeextrastuffafterimport();     }      private void dosomeextrastuffafterimport()     {     } } 

this gets rid of event subscription , instead handles override (which normal pattern in .net events).


Comments

Popular posts from this blog

python - pip install -U PySide error -

arrays - C++ error: a brace-enclosed initializer is not allowed here before ‘{’ token -

cytoscape.js - How to add nodes to Dagre layout with Cytoscape -