c# - how to account for disparate implementation needs? -
suppose have interface 2 concrete classes. 1 concrete needs implement idisposable
. should interface amended implement idisposable
benefit of 1 class or should consumer of interface have perform runtime checks disposability?
i assume interface should amended simple change (especially if new interface) can see possible violation of liskov in changing design suit particular implementation (especially if other class or classes have throw not supported exceptions)
if framework indication, appropriateness of having interface implement idisposable
depends on whether disposability necessary property fulfill contract interface defines. small number of framework interfaces implement idisposable
, including:
system.collections.generic.ienumerator<t> system.deployment.internal.isolation.store system.resources.iresourcereader system.resources.iresourcewriter system.security.cryptography.icryptotransform system.componentmodel.icomponent system.componentmodel.icontainer
by nature, these interfaces define constructs consume, , need release, resource. in sense, disposing of resources considered integral part of implementation contract, rather implementation detail of concrete classes implement interface. instance, iresourcereader
read resource, , closing resource necessary part of implementation contract.
in contrast, common in framework concrete classes implement idisposable
directly (not through interface). framework classes, can queried through reflection:
foreach (var v in typeof(/*any type*/) .assembly.gettypes() .where(a => a.isclass && typeof(idisposable).isassignablefrom(a) && a.getinterfaces().where( i=>i!=typeof(idisposable) ).all(i=>!typeof(idisposable).isassignablefrom(i)))) { foreach (var s in v.getinterfaces()) console.writeline(v.fullname + ":" + s.name); }
generally, these classes implementation requires consumption of resources, incidental fulfilling interface contract. instance, system.data.sqlclient.sqldataadapter
implements idbdataadapter
, idisposable
separately; possible idbdataadapter
not require disposition, implementation of sqldataadapter
requires consumption , release of resources.
in case, indicate there 2 classes implement interface, 1 needs implement idisposable
, , 1 not. given 1 not, ability dispose of resources definition not integral fulfilling requirements of interface; follows interface should not implement idisposable
.
incidentally, dispose()
should not throw exception (see ca1065: not raise exceptions in unexpected locations.) if class instance implements idisposable
has no resources dispose, can return; postcondition resources released satisfied. not necessary throw notsupportedexception
.
addendum
a second potential consideration anticipated usage of interface. instance, common use following pattern in database scenarios:
system.data.idbcommand cmd = ...; using (var rdr = cmd.executereader()) // returns idatareader (idisposable) { while (rdr.read()) {...} } // dispose
if idatareader
not implement idisposable
, equivalent code need more complex:
system.data.idbcommand cmd = ...; system.data.idatareader rdr; try { rdr = cmd.executereader(); while (rdr.read()) {...}; } { if (rdr idisposable) ((idisposable)rdr).dispose(); }
if type of usage expected common, may justify making interface idisposable
special case, if not implementations expected implement idisposable
.
Comments
Post a Comment