Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Having an interface include members which are usable on some objects that implement the interface but not all of them, and also includes a query method to say which interface members will be useful, is a good pattern in cases where something is gained by it.</p> <p>Examples of reasons where it can be useful:</p> <ul> <li><p>If it's likely than an interface member will be useful on some objects but not other instances <em>of the same type</em>, this pattern may be the only one that makes sense.</p></li> <li><p>If it's likely that a consumer may hold references to a variety of objects implementing the interface, some of which support a particular member and some of which do not, and if it's likely that someone with such a collection would want to use the member on those instances which support it, such usage will be more convenient if all objects implement an interface including the member, than if some do and some don't. This is <em>especially</em> true for interface members like <code>IDisposable.Dispose</code> whose purpose is to notify the implementation of something it may or may not care about (e.g. that nobody needs it anymore and it may be abandoned without further notice), and ask it to do whatever it needs to as a consequence (in many cases nothing). Blindly calling <code>Dispose</code> on an <code>IEnumerable&lt;T&gt;</code> is faster than checking whether an implementation of <code>IEnumerable</code> also implements <code>IDisposable</code>. Not only the unconditional call faster than checking for <code>IDisposable</code> and then calling it--it's faster than checking whether an object implements <code>IDisposable</code> and finding out that it doesn't.</p></li> <li><p>In some cases, a consumer may use a field to hold different kinds of things at different times. As an example, it may be useful to have a field which at some times will hold the only extant reference to a mutable object, and at other times will hold a possibly-shared reference to an immutable object. If the type of the field includes mutating methods (which may or may not work) as well as a means of creating a new mutable instance with data copied from an immutable one, code which receives an object and might want to mutate the data can store a reference to the passed-in object. If and when it wants to mutate the data, it can overwrite the field with a reference to a mutable copy; if it never ends up having to mutate the data, however, it can simply use the passed-in immutable object and never bother copying it.</p></li> </ul> <p>The biggest disadvantage of having interfaces include members that aren't always useful is that it imposes more work on the implementers. Thus, people writing interfaces should only include members whose existence could significantly benefit at least some consumers of almost every class implementing the interface.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    1. COIt's a good effort at an answer, so I'll award the bounty, but I don't find this complete enough to choose it as an answer. To your first bullet, you do not consider moving the API to a subclass/subinterface as I suggest in the question. Your second bullet point is irrelevant, as the IDisposable interface is not optional in the slightest, whereas I am considering an interface which can be considered, to some degree, optional. If something is IDisposable it is 99.999% of the time known at compile time. I am considering the case where it is known only at runtime, which is a different problem.
      singulars
    2. CO@sooniln: The relationship between `IDisposable` and enumeration interfaces doesn't perfectly fit the point I was trying to make, but it's a well-known part of the Framework that actually exists. Whether or not the object returned from the (non-generic) `IEnumerable.GetEnumerator()` method will implement `IDisposable` *cannot generally be known until run-time*. If one wants to imagine an optional hypothetical interface feature, how about imagining the convenience of having `IEnumerable` include a `Count` member, perhaps with an argument that would allow...
      singulars
    3. CO...for options such as "return the count if convenient, -1 if not convenient, -2 for a sequence that may be over 2^31 items, or -3 if boundless", or "return count if bounded below 2^31, or throw otherwise". Not all implementations of `IEnumerable` could have done anything useful with that method, and many might defer to a static `int ManuallyCountEnumerable(IEnumerable)` method, but the situation would have still been better than exists with the `IEnumerable.Count()` static method.
      singulars
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload