Just as classes can implement multiple interfaces, so interfaces can inherit from multiple interfaces. The syntax used for this purpose is consistent with class derivation and implementation, as shown in Listing 8.9.
It is unusual to have an interface with no members, but it is a reasonable choice when implementing both interfaces together. The difference between Listing 8.9 and Listing 8.6 is that it is now possible to implement IWriteableSettingsProvider without supplying any read capability. Listing 8.6’s FileSettingsProvider is unaffected. If it used explicit member implementation, however, specifying the interface to which a member belongs changes slightly.
Perhaps one of the most important features of extension methods is the fact that they work with interfaces in addition to classes. The syntax used is identical to that used for extension methods for classes. The extended type (the first parameter and the parameter prefixed with this) is the interface that we extend. Listing 8.10 shows an extension method for IListable() that is declared on the Listable class.
In this example, the extension method is not for an IListable parameter (although it could have been), but rather for an IListable parameter. This demonstrates that C# allows extension methods not only on an instance of a particular type but also on a collection of those objects. Support for extension methods is the foundation on which the Language Integrated Query (LINQ) capability is implemented. IEnumerable is the fundamental interface that all collections implement. By defining extension methods for IEnumerable, LINQ support was added to all collections. This radically changed programming with collections. We explore this topic in detail in Chapter 15.
Interfaces in a UML-like7 figure take two possible forms. First, you can show the interface as though it is an inheritance relationship similar to a class inheritance, as demonstrated in Figure 8.1 between IPerson and IContact. Alternatively, you can show the interface using a small circle, often referred to as a lollipop, exemplified by IPerson and IContact in Figure 8.1.
In Figure 8.1, Contact derives from PdaItem and implements IContact. In addition, it aggregates the Person class, which implements IPerson. Although the Visual Studio Class Designer does not support this practice, interfaces are sometimes shown as using a derivation-type arrow to a class. For example, Person could have an arrow to IPerson instead of a lollipop.