Saturday, November 9, 2019

C# 8 Interfaces: Public, Private, and Protected Members

When taking a closer look at C# 8 interfaces, we come across an interesting change: interface members can have access modifiers - public, private, and protected (and others).
Public members are what we are used to. Private members are useful for refactoring default implementations. Protected members may be useful for interface inheritance (but not much else).
Let's take a look at a few examples to show what we can and can't do with access modifiers and interface members.

The code for this article is available on GitHub: jeremybytes/interfaces-in-csharp-8.

Note: this article uses C# 8 features, which are currently only implemented in .NET Core 3.0. For these samples, I used Visual Studio 16.3.6 and .NET Core 3.0.100.

Public Interface Members
Prior to C# 8, interface members were public by default. In fact, if you put an access modifier on an interface member (including public), it would generate a compiler error.

The code for this section is available in the "Public" folder of the "AccessModifiers" project on GitHub.

Interface Members Default to "public"
In C# 8, interface members are still public by default. But since other access modifiers are allowed (as we'll see in a bit), public is also allowed.

In the following code, both of the interface members are "public" (from the ICustomerReader.cs file on the AccessModifiers project).

Both the "GetCustomers" method and the "GetCustumer" method are public. So whether we use the "public" keyword or no access modifier, the members of an interface are public.

Class Members Default to "private"
Classes in C# behave differently. Class members default to "private". Here is a sample of a "Customer" class with private members (from the Customer.cs file):

This class has 2 private fields: _familyName and _givenName. Neither of these fields are accessible outside of the class.

The main reason to point this out is that default access is different for interface members (public) and class members (private).
As a practice going forward, I will use "public" explicitly in my interfaces to reduce confusion.
Implementation Still Needs to be Marked "public"
Something important to note is that even though the interface members default to public, they still need to be explicitly marked as "public" in the implementation code.

Here is a snippet of the "FakeCustomerReader" class that implements the "ICustomerReader" interface that we saw above (from the FakeCustomerReader.cs file):

This code provides implementations for the "GetCustomer" and "GetCustomers" methods from the interface. But they both must be marked as "public" for the code to compile.

Even though "GetCustomers" does not have an access modifier in the interface (public default), it does require an access modifier in the implementation since classes default to private.

This is no different from interface implementations prior to C# 8. Even though interface members did not have access modifiers, the implementations required "public" implementation (unless they were explicit implementations -- we'll talk a little about explicit implementation further down).

Private Interface Members
Something new in C# 8 is that we can now have private interface members. Let's work through the why and how of private members by looking at some code.

The code for this section is available in the "Private" folder of the "AccessModifiers" project on GitHub.

Private Members Must Have Default Implementation
By definition, private members are not accessible outside of the current object. In our case, this means that a private interface member is not accessible from outside of the interface.

Consequently, there is no way to provide an implementation for a private interface member outside of the interface.

Fortunately, the compiler knows about this. The following code is not allowed (from the ICalendarItem.cs file):

In this code, we try to create a private read-only property for the interface.

Here is the error message:

This tells us that we *must* declare a body (i.e., a default implementation) for this member. (Note: we won't get into the "abstract, extern, or partial" in this article. We'll look at those in future articles.)

So to make our code happy, we must provide a default implementation (from the ICalendarItem.cs file):

This adds a default implementation to the "DefaultType" property.

As a side note, "CalendarItemType" is an enum defined in the ICalendarItem.cs file.

Private Members are Useful for Other Default Implementations
Since private members are not accessible from outside of the interface itself, they are really only useful for default implementations of other interface members.

Here's an overly-simplified example (from the ICalendarItem.cs file):

Here we have another interface member: a public property called "ItemType". This has a default implementation that uses the private "DefaultType" property.

Again, this is an overly-simplified example. The primary purpose that I've seen for using private members on interfaces is to extract methods and refactor code to smaller pieces.

Here's the problem that I have with those examples: if the code in the interface implementation is so large that we feel the need to refactor, then is this really an interface? At some point we will need to decide whether we keep interfaces as abstractions or turn them into active code files.

In my current opinion (which is subject to change), if we add too much code to interfaces, then they are no longer "interfaces". I really wish that these new features were added under a new name or syntax. At some point the word "interface" becomes meaningless. But that's a discussion for another time.

Private Interface Properties are Read-Only
In thinking about private members, we should consider what we learned about properties and default implementation. In a previous article (Properties and Default Implementation), we saw that default implementation does not make sense for read-write properties. It is good for calculated or constant read-only properties.

Since private interface members must have default implementation, we can extend this to mean that private interface properties should also be read-only.

This isn't really ground-breaking, just another thought that came up while I was exploring code.

Private Interface Members are not Accessible by Implementing Classes
As stated above, private interface members are not accessible from outside of the interface itself. This means that an implementing class cannot access private members (which should not be a surprise).

Just to show this, here is some code from a "CalendarEvent" class that tries to access the private member (from the CalendarEvent.cs file):

This code tries to assign to the private "DefaultType" member of the interface.

The error message tells us that "DefaultType does not exist in the current context."

This is the same message that we would get when trying to access a private member on any other type.

Protected Interface Members
The last thing that we'll look at today is protected interface members. This is the strangest (and probably least useful) of the access modifiers here.

The code for this section is available in the "Protected" folder of the "AccessModifiers" project on GitHub.

I'm not sure how this works completely. So the examples here are from my experimentation. In the language proposal for default interface methods, the issue is left open:

"Open Issue: We need to specify the precise meaning of the access modifiers such as protected and internal, and which declarations do and do not override them (in a derived interface) or implement them (in a class that implements the interface)."

There may be a GitHub issue that resolves this; however, I haven't had any luck finding one so far. Here's what I've found through experimentation.

Protected Interface Members are Allowed
As an experiment, I created an interface that has a protected member (from the IInventoryController.cs file):

This interface has 2 members: a public "PushInventoryItem" method and a protected "PullInventoryItem" method.

Protected Interface Members *Must* be Implemented Explicitly
The next thing I found is that protected interface members must be implemented explicitly.

If we try to implement a protected member "normally", we get an error. Here's code for a "FakeInventoryController" (from the FakeInventoryController.cs file):

This has implementations for both the public member and the protected member, but the red squigglies under the interface name tell us that something is wrong.

The error message tells us that we have an incomplete implementation of the interface: "FakeInventoryController does not implement interface member PullInventoryItem".

Changing the access modifier on the affected item does not change anything. The only way to satisfy the interface is to implement the interface member explicitly.

Here is the explicit implementation (from the FakeInventoryController.cs file):

With explicit implementation, we do not provide an access modifier on the implementation. In addition, the declaration "IInventoryController.PullInventoryItem" specifies that this code can only be called using the explicit interface type. (We'll see this in just a bit.)

To show the differences between the public and protected members of the interface, the final code shows both interface members implemented explicitly (from the FakeInventoryController.cs file):

This code compiles without errors.

There is No Way to Access the Protected Interface Implementation
This is where things get really strange. We have an interface with a protected member (this compiles fine). We have a class that explicitly implements that interface (this compiles fine). But we can *not* access the protected implementation.

The root of the AccessModifiers project on GitHub has a Program.cs file to test this.

This code creates an instance of the "FakeInventoryController" class and assigns it to an "IInventoryController" variable.

Note that it is important that the variable is the interface type. When using explicit implementation, we can only access the interface members through the interface type. (For more information on explicit implementation, take a look at this article: Explicit Interface Implementation.)

When we access the "PushInventoryItem" method (the public interface member), everything works as expected.

But when we access the "PullInventoryItem" method (the protected interface member), we get a compiler error.

The error tells us that "PullInventoryItem is inaccessible due to its protection level". So even though we have access to the member through the class (and the explicit implementation), we cannot call that implementation. This is true even though we are using the interface as the type.

Using Protected Interface Members
If we can't use protected interface members, then what are they there for? As noted in the "Open Issue" that we saw above, protected members may be useful when we have interface hierarchies (meaning, one interface inherits from another interface).

I haven't done any experiments with this because I try to keep things simple. I do use interface inheritance, but I do this to compose interfaces and add new members. I do not do this to try to override base behavior or get into polymorphism. I've generally found that if you try to be to clever with polymorphism and determine which method gets called depending on the situation, it's very difficult for the humans to follow along.

So I'll leave this as an exercise for the reader.

Broken Tooling with Protected Members
Visual Studio tooling is generally really awesome, but the current tooling breaks down with protected interface members (at least with Visual Studio 2019 16.3.6).

I love to use the Quick Actions in Visual Studio (particularly to implement interfaces). You get to this by clicking the lightbulb icon or by using "Ctrl+." with the cursor on the interface.

When implementing an interface with these tools, the explicit implementation works just fine:

Using "Implement interface explicitly" generates both methods as explicit implementations (which is what we have in the final code).

But if we try to use "Implement interface" (the non-explicit version), we run into problems:

This only generates implementation for one of the members (the public one).

And as we saw earlier, this leads to an incomplete implementation:

Note the red squigglies that we saw earlier. This is because we do not have an implementation for the protected member.

The reason that I'm a bit disappointed by this is because Visual Studio has been really smart with implementations in the past. For example, if there were conflicting interface members (meaning 2 interfaces with the same method name and parameters, but different return types), Visual Studio would implement the conflicting members explicitly (even if you asked for the non-explicit implementation).

I'm hoping that this will be fixed in a future update.

Wrap Up
Interfaces in C# 8 have changed significantly. Adding access modifiers creates a lot of interesting things to thing about.

"Public" is still the default, and this is what we should use most of the time. As mentioned, I've started explicitly using the "public" keyword to reduce confusion.

"Private" is useful for members that will be used for other default implementations. This is a way to break up the code into smaller pieces. (As noted above, whether our interfaces should get this complex is something to consider.)

"Protected" is there, but not very useful. It may be useful in interface hierarchies, but it cannot be used directly through explicit implementation.

There's lots to think about. To get the code and links to other articles, be sure to visit the GitHub repo:

Happy Coding!

Friday, September 27, 2019

C# 8 Interfaces: Unit Testing Default Implemetation

When taking a closer look at C# 8 interfaces, we need think about unit testing. We (potentially) have code in our interfaces; how do we test it?
We can test default implementations with our own fake objects, however, we cannot test them with mocking-framework objects (at least for now).
Once we take a closer look at some tests and understand what mocking frameworks do for us, this will make a bit more sense. Hopefully our favorite frameworks will give us an easy way to test default implementations in the future, but for now we have to do things a bit more manually.

The code for this article is available on GitHub: jeremybytes/interfaces-in-csharp-8.

Note: this article uses C# 8 features, which are currently only implemented in .NET Core 3.0. For these samples, I used Visual Studio 16.3.1 and .NET Core 3.0.100.

This article uses 2 projects. UnitTests.Library is a .NET Standard 2.1 class library that contains the interface. UnitTests.Tests is a .NET Core 3.0 NUnit unit test project; this contains the tests.

Testing Default Implementation
I am a big believer in unit testing. When I put code into my projects, I think of how the code can be written so that it is easy to test. The same is true when it comes to default implementation in interfaces. The basics involve just a few steps.

An Interface
Here's the interface that we use for these tests, IRegularPolygon (from the IRegularPolygon file in the UnitTests.Library project):

This interface describes a regular polygon -- meaning, a shape that has 3 or more sides where each side is the same length. The "GetPerimeter" method has a default implementation, and this is what we want to test.

A Fake Object
For the first test, we will use a fake object. This is a manually-created class that implements the interface.

Here is the code for the FakeWithDefault class (from the IRegularPolygon.Tests.cs file in the UnitTests.Tests project):

This class provides implementations for the abstract members of the interface, but it does *not* provide an override for the GetPerimeter method. It relies on the default implementation from the interface.

A First Test
Now that we have the interface and an implementing class, we can write our first unit test. Here is the code for that (from the IRegularPolygon.Tests.cs file -- the rest of the code samples will come from this file):

This test creates an instance of our fake object and assigns it to an IRegularPolygon variable.

It is important to specify that the variable is "IRegularPolygon". If we use "var" or "FakePolygonWithDefault" as the type, then the GetPerimeter method will not be accessible.

The next line calls the GetPerimeter method on the interface. This will use the default implementation.

The last line checks the value of the output. Our fake object uses the values of "4" and "5" for NumberOfSides and SideLength, respectively. So we expect that the value of GetPerimeter is 4 * 5, or 20.

This test passes:

So we can see that we can test a default implementation with just a few steps. We create a class that implements the interface but does not override the default implementations from the interface. In the test, we create an instance of that class and cast it to the interface. Finally, we call the member with the default implementation and check the result.

Testing with a Mocking Framework
Sometimes I manually create fake objects for my unit tests, but I generally use a mocking framework instead. This reduces the number of objects in the unit test projects. And once we're comfortable with a particular framework, we can quickly create test objects with a variety of configurations.

Unfortunately, we cannot test default implementation with the way that mocking frameworks work today. Let's start by looking at an example using Moq (the framework I generally turn to).

Creating a Mock with Moq
The test project includes a NuGet reference to the Moq package. With that in place, we can write a test that uses a mock object:

When using a mocking framework, we tell the framework how to create and configure our test object. The first line of our test creates a mock based on the IRegularPolygon interface.

The next two lines set up the mock with specific values for the NumberOfSides property and the SideLength property. In this case, if we ask the mock for "NumberOfSides", it will give us "3"; if we ask for "SideLength", it will give us "5".

The setup does *not* include configuration for the "GetPerimeter" or the "GetArea" methods. This is a key feature of mocking frameworks, and we'll discuss this further down.

The 4th line calls the "GetPerimeter" method on our mock object. (The variable "mock" is a "Mock<IRegularPolygon>". When using Moq, the "Object" property represents the "IRegularPolygon" object.)

The last line checks the results.

Unfortunately, we do not get the results we want.

This test fails. When we look at the Error Message, we see that the value was "0.0d" (meaning 0 as a double) instead of the expected "15.0d".

Expected Behavior
This is the expected behavior from Moq (and mocking frameworks in general). When we configure a mock object, we only need to fill in the items that we use. And that can be a big time saver, particularly if we need to quickly mock up a dependency needed for a test.

When we create an object manually (FakePolygonWithDefault), we need to provide implementations for all of the abstract members of the interface. This means that we have to provide an implementation for "GetArea" even though we do not use that method in the tests.

When we create a mock object using a framework, we only need to provide implementations for the things we care about. The mocking framework will take care of the rest.

In the unit test using Moq, we do not need to provide a configuration for the "GetArea" method because we do not use it in the tests. If, for some reason, a test calls the "GetArea" method, the mocking framework will return the default value. Since "GetArea" returns a double, the default value is "0.0d".

Does this value look familiar? We *are* using the "GetPerimeter" method in our tests. But instead of getting the default implementation from the interface, we are getting the default value from the mocking framework. Since "GetPerimeter" also returns a double, the default value is "0.0d". This is the value we see in the failing test.

Explicit Configuration
We can explicitly configure the mock object with the "GetPerimeter" method:

And it works. This test passes:

But this does not use the default implementation; it uses an explicit implementation.

Other Frameworks
I tried a couple of other frameworks: NSubstitute and FakeItEasy. These both provided similar results.

Here is a test using NSubstitute without an override of the default:

And with an override:

And the test results are similar to using Moq:

Again, this isn't a surprise if we understand how the mocking frameworks work.

Here is a test using FakeItEasy. First without an override of the default:

And with an override:

And the results:

Again, we see similar behavior to the other frameworks.

Will Mocking Frameworks Change?
All of this is still really new. C# 8 with default implementation released at the beginning of this week. So the fact that these mocking frameworks do not support default implementation by default is not surprising.

Will this change in the future?

I'm not sure. I have not done extensive searches. But in my preliminary search I haven't seen anything about default implementation, and these particular packages do not currently have pre-release versions on NuGet.

Update: As Blair Conrad notes in the comments, FakeItEasy has an open issue for supporting default implementation: Issue - Support for calling default interface members.

Here are the versions that I used for this project:

I will keep an eye on this because I'm curious how mocking frameworks will adjust with default implementation in interfaces.

It may be difficult to change the default behavior. If someone does *not* configure an interface member, do they expect to get the default value (current behavior) or the default implementation from the interface (new behavior)? Changing the current behavior could result in breaking changes.

Testing Manually
Whichever way the mocking frameworks go, we can test default implementations manually. We can create classes that do not override the default and then use those objects in our tests.

Default implementation in interfaces gives us a lot of new things to think about. I'm most concerned with how it affects the existing code, techniques, and processes that I already have (and other people have). Once we get the current things worked out, it will be easier to figure out how to move forward in the best way we can.

Happy Coding!

Thursday, September 26, 2019

C# 8 Interfaces: "dynamic" and Default Implementation

In taking a closer look at C# 8 interfaces, I ran across a bit of a bug when using "dynamic" with default implementation members.
A "dynamic" object cannot see interface members with only default implementations.
This is something I came across when exploring properties and default implementation. But it's interesting enough to warrant a closer look.

The code for this article is available on GitHub: jeremybytes/interfaces-in-csharp-8, specifically the DynamicAndDefaultImplementation project.

Note: this article uses C# 8 features, which are currently only implemented in .NET Core 3.0. For these samples, I used Visual Studio 16.3.1 and .NET Core 3.0.100.

An Interface with Default Implementation
To show how dynamic works (or doesn't work), we'll use an interface with a default implementation for a method. The example here is an interface that represents a regular polygon -- that is, a geometric shape with 3 or more sides where each side is the same length.

Here is the interface (from the IRegularPolygon.cs file):

The "GetPerimeter" method has a default implementation and uses the expression-bodied member syntax. Since the perimeter of a shape is calculated the same regardless of the number of sides, we can provide a default implementation in the interface. (Whether this is a good approach or not is going to be discussed in a future article.)

The Implementation
This interface is implemented by the Square class (from the Square.cs file):

As shown here, the Square class provides implementations for the NumberOfSides and SideLength properties from the interface, and it has an implementation of the GetArea method from the interface (this also uses the expression-bodied member syntax).

Notice that the GetPerimeter method is *not* implemented. The class instead relies on the default implementation provided by the interface.

Using the Implementation
This project is a console application, and the Main method creates two Square objects and displays them (from the Program.cs file -- the final file has some error handling that isn't shown here):

Showing Members with the Interface
Here is the "ShowInteracePolygon" method (also from the Program.cs file):

This method takes our interface as a parameter. Then it displays the properties and methods that are part of the interface. This method call works fine with both of our Square objects.

The first call is made with "smallSquare". Since "smallSquare" uses "var", the variable is a Square type. (For more information on "var", take a look at Demystifying the "var" Keyword in C#.) But because the parameter is "IRegularPolygon", the "smallSquare" gets cast to the interface for use in the method.

The second call is made with "largeSquare". This variable is explicitly typed as "IRegularPolygon", so there is no casting necessary when the method is called.

A Problem with Dynamic
The problem comes in with the "ShowDynamicPolygon" method. I have used "dynamic" in the past so that a method can work with various types that all have the same properties and methods even if the types are incompatible.

As a side note, I also like to use "dynamic" when I need to pick one or two values out of a deserialized JSON object. This saves me from having to create a separate class or do mapping. There are risks of runtime errors, but sometimes it is worth the risk.

Here is the code for ShowDynamicPolygon (also in the Program.cs file):

The body of the method is identical to "ShowInterfacePolygon". The only difference is that the parameter is typed as "dynamic".

Unfortunately, this fails.

Failure with the Concrete Type (Square)
The first call to this method (using "smallSquare") fails:

The exception is a RuntimeBinderException. This is thrown when the Runtime Binder cannot find the requested member on the object. In this case, the exception tells us that "GetPerimeter" is not part of the "Square" class.

And that is absolutely correct. If we look back at the Square class, we see that it does not have a "GetPerimeter" method:

So this failure makes sense.

Failure with the Interface (IRegularPolygon)
The second call to the method (using "largeSquare") also fails:

This is a bit more difficult to understand. The "largeSquare" variable is typed to our interface, IRegularPolygon, and the interface *does* have the "GetPerimeter" method.

But that is not how "dynamic" works here. If we look at the exception, we see that we have the same message that we saw earlier: "GetPerimeter" is not part of "Square".

The Runtime Binder is not looking at the type of the object, it is looking at the object itself. Specifically, it is looking at the visible members of the object. Since the object is a "Square", that is what the Runtime Binder sees.

Bug or Intended?
I'm not sure if this is a bug or if this is how it is intended to work. In looking through the design proposal, I did not see any references to "dynamic". So this may be an oversight.

Or it might be intentional. "dynamic" and the DLR (dynamic language runtime) haven't gotten much love lately. The issues in the GitHub repository for .NET are a bit complicated (and there are a ton of them), so I haven't taken the time to research whether this shows up as an issue in the repository.

Some Error Handling
To avoid runtime exceptions, the final code has some try/catch blocks (in the Program.cs file):

This catches the RuntimeBinderException and shows the message on the console. Here's what that output looks like:

So, we can see that "dynamic" cannot see the default implementation of an interface member.

But then if we keep going, things get a bit more interesting.

Inconsistent Behavior
Understanding how "dynamic" behaves with default implementation is good on the surface, but things get strange if we have some classes that use the default implementation and some classes that override the default.

Here's a Triangle class (from the Triangle.cs file):

Triangle also implements the IRegularPolygon interface. But notice that it provides its own implementation for the "GetPerimeter" method. This overrides the default behavior in the interface itself.

We can create an display the triangle (in the Program.cs file):

And everything works!

This shows that both the "ShowInterfacePolygon" and "ShowDynamicPolygon" methods work with the Triangle class.

The Difference
The difference is that Triangle has its own GetPerimeter method, so the Runtime Binder finds it when using the "dynamic" parameter.

Now this seems a bit dangerous. The "dynamic" method works sometimes but not others.

If a class relies on a default implementation, it fails:

And if a class provides its own implementation, it succeeds.

This is a little bit scary.

Wrap Up
So we need to be a bit careful when using "dynamic" around interfaces that have default implementations for members. If a default implementation is used, then "dynamic" will fail to find it. If the class provides its own implementation, "dynamic" finds it just fine.

The changes in C# 8 make interfaces more complicated than I would like them to be. But digging into them and exploring is how we figure out what works and what doesn't work.

After we have a good handle on the mechanics, we can take a closer look at how to use the new features in a safe and understandable way. But that will have to wait for a future article.

Happy Coding!