Question

Does this IConvertible interface satisfy the Interface Segregation Principle (ie. the "I" in SOLID)?

Here is the definition:

public interface IConvertible
{
    TypeCode GetTypeCode(); 
    bool ToBoolean(IFormatProvider provider);
    byte ToByte(IFormatProvider provider);
    char ToChar(IFormatProvider provider);
    DateTime ToDateTime(IFormatProvider provider);
    decimal ToDecimal(IFormatProvider provider);
    short ToInt16(IFormatProvider provider);
    int ToInt32(IFormatProvider provider);
    long ToInt64(IFormatProvider provider);
    sbyte ToSByte(IFormatProvider provider);
    float ToSingle(IFormatProvider provider);
    string ToString(IFormatProvider provider);
    object ToType(Type conversionType, IFormatProvider provider);
    ushort ToUInt16(IFormatProvider provider);
    uint ToUInt32(IFormatProvider provider);
    ulong ToUInt64(IFormatProvider provider);
}

So if I would like to have a class which will implements this IConvertible interface the I have to implement all of those methods, right? Or if I don't implement all of them, then I have to at least make an empty method or throw an Exception, right?.

In my opinion, the better way is to make more interface with fewer methods, for example:

public interface IConvertibleInt
{
        short ToInt16(IFormatProvider provider);
        int ToInt32(IFormatProvider provider);
        long ToInt64(IFormatProvider provider);
}

Or even:

public interface IConvertibleInt16
{
        short ToInt16(IFormatProvider provider);
}

public interface IConvertibleInt32
{            
        int ToInt32(IFormatProvider provider);
}

public interface IConvertibleInt64
{
        long ToInt64(IFormatProvider provider);
}

Is my reasoning correct?

Was it helpful?

Solution

I like to interpret Interface Segregation Principle as

Interface should be closer related to the code that uses it than code that implement it. So the methods on the interface are defined by which methods client code needs than which methods class implements.

This implies that for each interface, there is always code that uses this interface. This is not the case of IConvertible. The interface itself doesn't make much sense. I also never saw property or function that was typed IConvertible, which empowers my claims. I even wonder how would code that only works on IConvertible looks and what would it do.

OTHER TIPS

One difficulty with applying the Interface Segregation Principle in .NET is that any given storage location must have a single specified type. If there had been separate interfaces for IConvertibleToInt32, IConvertibleToInt64, then a type which only supported some of the conversions would only have to implement the ones it supported; code which needed exactly one conversion interface could accept a parameter of that type. Unfortunately, splitting things up in that fashion would make it difficult to write code which needs more than one conversion interface. For example, if a method needed to use IConvertibleToInt32, but which needed to pass an object to a method that needed IConvertibleToInt64, there would be no way to specify that it needed an object which supported both interfaces unless there were existed an interface which inherited from both and all types of interest which implement both interfaces also implement the composite one.

If .NET made had a means of defining a special kind of "composite" interface such that any class which implemented all of the components would automatically be regarded as an implementation of the composite, then it would make sense to subdivide interfaces much more finely. The lack of such ability, however, makes it necessary to define interfaces which are much coarser than would be ideal.

IConvertible neither violates nor conforms to the Interface Segregation Principle. The principle is followed or not by classes that depend on the interface, not by the interface.

One class could depend on the interface and use every method, not violating the principle. Another could depend on the interface and use one method, violating the principle. Does this mean that IConvertible both violates and does not violate the principle? No. It means that one class depending on it does and the other does not.

Yes, IConvertible is a weird interface, but in isolation it doesn't illustrate the ISP.


It's also worth considering the reason behind the principle, which is that if multiple classes depend on different methods of an interface, one "client" might exert backwards pressure to change the interface, which means modifying an interface and possibly implementations which could affect unrelated code. It's a form of coupling.

It's very unlikely that IConvertible will change to meet the needs of any individual clients, so the risk which is the reason for the principle is mitigated.

Licensed under: CC-BY-SA with attribution
scroll top