Tuesday, September 24, 2019

C# 8 Interfaces: Properties and Default Implementation

In taking a closer look at C# interfaces, we'll start by exploring default implementation and how it relates to properties. Here's what I've found:
Default implementation is really good for calculated properties; it's not so good for read/write properties.
The code for this article is available on GitHub: jeremybytes/interfaces-in-csharp-8, specifically the InterfaceProperties 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.0 and .NET Core 3.0.100.

Default Get
Let's start by looking at an interface that has a default "get" for a property. Here's an interface that describes a regular polygon and has a default implementation (from the IRegularPolygon.cs file):


This describes a regular polygon -- a geometric shape with 3 or more sides where each side is the same length.

The interface describes four properties. (1) NumberOfSides is a read-only property that tells how many sides the shape has. This is read-only because we do not want type of shape (triangle, square, etc.) to change after it is created.

(2) SideLength is a read/write property. The size of the shape is allowed to change during its lifetime.

(3) Perimeter is the distance around the shape. This is a calculated property. Since the calculation is the same for every shape, we included a default implementation.

This code uses the expression-bodied member syntax to return the number of sides multiplied by the side length. If you're not familiar with expression-bodied members, this is the equivalent of the following code:


The expression-bodied member syntax is a short-hand that removes the braces and the "return" keyword. I'll be using the shorter syntax throughout this article, but they are equivalent in functionality. Read more here: Expression-bodied members - Properties.

(4) Area is the space inside the shape. This is also a calculated property, but the calculation is different from each shape. Because of this, we do not provide a default implementation. It will be up to each class to specify it's own calculation.

A Shorter Default Get
There is a slightly shorter way to specify a default "get" for a property (from the IRegularPolygon.cs file):


This is a shorter version of the expression-bodied member syntax that can be used with read-only properties. In this case, we can get rid of the "get" keyword and the braces around that.

This syntax makes it a bit harder to tell whether this is a property or a method. (The difference is that an expression-bodied method would have empty parentheses after "Perimeter".) Read more here: Expression-bodied members - Read-only properties.

Implementing the Interface
Here is a square that implements this interface (in the SquareFromInterface.cs file):


This class implements the IRegularPolygon interface. It provides automatic properties for NumberOfSides and SideLength, and it has a constructor that initializes those properties. There is also an implementation for the Area property. This uses the same expression-bodied member syntax shown above.

One thing to note is that the Perimeter property is not implemented in this class. It relies on the default implementation provided by the interface.

Using the Class
This project is a console application, and we use this square class in the Program.cs file.


This code creates 2 instances of the SquareFromInterface class and displays the properties to the console. The output is unsurprising:


An important thing to note about this code is that accessing the "Perimeter" property from the ShowInterfacePolygon method works. Since the parameter (polygon) is IRegularPolygon, it uses the default implementation for Perimeter.

The Property is on the Interface Only
In this case, the concrete type, SquareFromInterface, does not have a Perimeter property. The property exists only as part of the interface. We can see this if we try to change the type of the "polygon" parameter to our concrete type:


In this code, the parameter is "SquareFromInterface". This type does not explicitly have the Perimeter property, so the code fails to build. (We can see the red squigglies under "Perimeter" in the code sample above.)

Overriding the Default Implementation
If we wanted to, the SquareFromInterface class could provide its own implementation of Perimeter. If it did provide that implementation, then that is the value that would be used, even if we cast the type to the interface. We'll take a closer look at how this works in a later article when we look at default implementation for methods.

Default Implementation for Read/Write Properties
There are some restrictions on default implementation for properties. When we have both a getter and a setter, we must provide implementations for both get/set or neither.

These examples are not valid (from the IBadInterface.cs file):


The first property has a default implementation for the get, but an abstract set (meaning, the implementing class needs to provide that). This is not allowed.

The second property has an abstract get with default implementation for the set. (The default implementation happens to be an empty method.) This is also not allowed.

For read/write properties, we need to provide default implementation for both get and set or for neither.

Note: when we provide default implementation for neither get nor set, we just end up with a regular abstract interface property like "SideLength" above.

Default Implementation for Set
Now that we've talked a little about read/write properties, the next question is whether default implementation makes sense for a read/write property, specifically how do we come up with a default implementation for "set".

No Automatic Implementation
Something to think about: there is no way for us to create an automatically implemented property (or auto property) as a default implementation. Let's look at this more closely. Here is the code from the SquareFromInterface class that we saw above:


Both NumberOfSides and SideLength are auto properties, meaning the compiler fills in some gaps for us. For example, the SideLength property really means this:


This is a property with a backing field. Since the "get" simply reads the backing field, and the "set" simply sets the backing field, this can be shortened to the auto property syntax that we have above. (As a side note, that is why the field is grayed-out; Visual Studio is telling us we can make this an auto property.)

The problem with automatic properties is that they use a backing field. This is instance data on the class. Interfaces are not allowed to have any instance data, so we cannot have backing fields in the interfaces.

This means that we can *not* create a property in an interface with an implementation that is an automatic property.

What Can We Put in the Setter?
The next question is whether there is anything that we can put into a default setter that would make sense. I'm not sure there is. (If you have any ideas, be sure to share them in the comments.)

Based on auto property syntax, it's tempting to try something like this for the setter (from the IBadInterface.cs file):


Unfortunately, this code compiles. It's tempting because it feels like we can cheat the auto property syntax for the setter. But in reality, it creates a Stack Overflow.

To show this, we implement this bad interface in an empty class (from the BadObject.cs file):


Since this object has no members, it uses the default implementation from the interface.

Here is some code to use that object (from the Program.cs file):


We can create the object with no problems. But if we try to set the BadMember property, bad things happen, specifically we get a Stack Overflow:



This isn't a surprise. When we set the "BadMember" property, it calls the setter which takes the value and uses it to set the "BadMember" property, which calls the setter for the "BadMember" property... You can see the problem.

Now this problem isn't any different from code that isn't using default implementation. If we create a property setter like this in a class, we will get the same Stack Overflow exception. The difference is that it's a bit more tempting to try something like that with default implementation in the interface to try to mimic what we would get from an automatic property.

Do Setters Make Sense?
Based on the fun that we've had here, I've wondered if there is a scenario where a default implementation for a property setter would make sense. So far, I haven't come across one. Be sure to share you ideas of you've got them.

Greenfield Abstract Class
If I was implementing the regular polygon scenario in a greenfield application (meaning, brand-new code), then I would probably use an abstract class. The implementation for the "Perimeter" calculated property would be just the same. But we could get some more safety for the NumberOfSides and SideLength properties.

Just to show the differences, I coded up the same functionality as an abstract class (from the AbstractRegularPolygon.cs file). First the NumberOfSides property:


The setter in this property has a guard clause to make sure that there are at least 3 sides to our polygon.

The SideLength property has a similar guard clause to make sure the length is greater than zero:


The rest of the class has a constructor to set the properties, and declarations for Perimeter and Area that look very similar to the interface:


The main difference is that for the abstract class, we mark Area as "abstract". We don't have to mark Area as "abstract" in the interface because that is the default.

Another Square Implementation
In the sample, we have a square class that inherits from the abstract class (from the SqureFromAbstractClass.cs file):


This class is a bit shorter than the one that implemented the interface. That's because it does not need to provide implementations for NumberOfSides or SideLength -- these come from the base class. The constructor calls the base class constructor with a hard-coded "4" for the number of sides.

Then we have an override of the Area property. This looks the same as our other square class.

Using the Square
The console application has code to use SquareFromAbstractClass (in the Program.cs file):


This code creates 2 instances from the interface class and 2 instances from the abstract class class. There is a different display function for the abstract class:


This is almost the same as the code that displays the interface properties. The only difference is the parameter type.

And we get similar output:


Since the display functions are so similar, it would be nice to combine them. In other samples, I've used "dynamic" to create a shareable method. But I ran into some problems when I tried that here.

Issues with Dynamic and Default Implementation
The regular polygon code is taken from a sample I use when teaching interfaces. For that code, I use a single method that can display multiple unrelated types. (The code is on GitHub if you're interested: DisplayPolygon sample.)

I ran into a problem when I tried that with the code that we have here. Here is a shareable method (from the Program.cs file):


This uses a "dynamic" as a parameter. This means that it is resolved at runtime rather than compile time. The good thing about this is that it will work with any object. And as long as the property or method is available on the object at runtime, everything works fine.

Or it almost works in this case.

Here's the code that calls the method:


But when using the dynamic method with the default property implementation, we get a runtime exception:


This is telling us that the runtime binder cannot find the "Perimeter" property on the "SquareFromInterface" object.

This is true. The "SquareFromInterface" class does not have its own "Perimeter" property. Instead, it relies on the default implementation from the interface.

You might be thinking that we need to pass to cast the object to the interface type before we pass it to the method. Well, it turns out that we did do that:


The "largeSquare" variable that we use is an IRegularPolygon (our interface). But even though we pass that type through, the runtime binder picks up the concrete object.

I don't know if this is a problem with the runtime binder, or whether this is intentional. I'll just leave a warning that when relying on a default implementation of an interface, there may be problems when combining it with "dynamic" objects.

Just as a note: the "dynamic" method works just fine with the abstract class class since "Perimeter" is part of the base class.

Update: I explored this behavior a bit further: C# 8 Interfaces: "dynamic" and Default Implementation.

Wrap Up
There has been a lot to think about. Default implementation seems like it can be really useful for calculated properties, particularly if we need to add a property after the interface is in a production environment.

But when it comes to setters for properties, default implementation doesn't seem to make much sense. And it's easy to get a stack overflow if we include a self-reference in the implementation.

As a reminder, you can get the code (and additional article links) from the GitHub repo: jeremybytes/interfaces-in-csharp-8.

We have a good idea of what the mechanics are for default implementation for properties. In future articles, we'll look at some guidance on default implementation in general.

Happy Coding!

Monday, September 23, 2019

A Closer Look at C# 8 Interfaces

There are a lot of changes to interfaces in C# 8 -- not just default implementation. Last time, I had a bit of a rant about those changes. Now it's time to settle down and take a closer look at what those changes are and better understand them.

The short list of changes includes the following:
  • Default implementation
  • Access modifiers
  • Static members
And there are a lot of smaller things that come up once we start looking at these features.

This is too much to talk about in one article, so the next several articles will be looking at these items more closely. I've been looking at the preview versions of .NET Core 3.0 (the first environment to support these features). Now that .NET Core 3.0 has been released, we can dive into code to see what is there, what is possible, what the compiler allows, and what the runtime allows.

Update: If you would like a video walkthrough with lots of code, take a look at this talk from the Phoenix-area user groups: https://www.youtube.com/watch?v=on-MIseN6gU (recordded 24 June 2020).

Default Implementation
Default implementation allows us to add implementation code to our interfaces. This means that we can provide method bodies for interface methods, events, indexers, and properties.

In looking at default implementation, there are a few questions that we will try to answer.

Property Get / Set
There are some things to explore about properties. For example, can you provide a default for a getter or setter separately, meaning a default implementation for a getter with an abstract setter? (The short answer is no.)

Update - Article now available: C# 8 Interfaces: Properties and Default Implementation.

Property Setter?
Since interfaces do not have any instance members (such as backing fields for properties), does it make sense to provide a default implementation for a setter? Is there a useful setter that we can provide?

Update - Article now available: C# 8 Interfaces: Properties and Default Implementation.

Generic Implementations
Would it be useful to create an interface that *only* has members with default implementation? If they have generic type parameters, this may be a way to add functionality to classes by only noting the interface and not changing the class itself.

Guidelines for Defaults
I've already seen an article with a really bad example of default implementation. The example makes assumptions about the concrete types that will be used and creates a scenario that would break implementations and make unit testing difficult.

Based on this, we need to take a look at what we put into default implementations to make sure that we keep a good environment for the folks using our interfaces.

Update - Article now available: C# 8 Interfaces: Dangerous Assumptions in Default Implementation.

Unit Testing
Now that we have code in our interfaces, how do we test it appropriately? On the surface, it seems like we can create a mock object and go. But some interesting things may pop up once we start looking at this more closely.

Update - Article now available: C# 8 Interfaces: Unit Testing Default Implementation.

Update: "dynamic"
In experimenting with default implementations, I found that "dynamic" does not find members that only have default implementations.

Article: C# 8 Interfaces: "dynamic" and Default Implementation.

Access Modifiers
Previously, interface members were automatically public. Now, members can have access modifiers including private, protected, internal, and public.

There are things that we will explore deeper in future articles.

Public Members
Public members really aren't a change since that's all we had before. But we need to take a look at how interface defaults differ from class defaults. For example, if we do not specify an access modifier on a class member, it defaults to private. But if we do not specify an access modifier on an interface member, it defaults to public. Not a huge deal, but we need to be aware of those differences.

Update - Article Now Available: C# 8 Interfaces: Public, Private, and Protected Members.

Private Members
Private members are new. These are not accessible outside of the interface itself. On the surface, this does not seem very useful for an interface since it is all about enforcing members on a class/struct. But private methods can be used by other members that have default implementation.

Private members *must* have a default implementation (because there is no way to add implementation outside of the interface itself).

Along with this, we need to take a look at what happens to our code once we start using private members. Will standard refactoring work? How does this affect testing? Can we treat this type of code (method extraction, small pieces, etc.) the same way we treat code in classes?

Update - Article Now Available: C# 8 Interfaces: Public, Private, and Protected Members.

Protected / Internal Members
Protected and internal members are also new, and we need to explore a bit further. What are the use cases for protected members? Are they useful only when deriving interfaces from other interfaces?

Also, how do these members impact the implementing classes? The short answer is that protected and internal members must be implemented explicitly in the class. The longer answer will depend on the use cases that we can come up with.

Update - Article Now Available: C# 8 Interfaces: Public, Private, and Protected Members.

Static Members
Another new feature is that we can have static members in interfaces. This includes static methods, static fields, and static constructors. These static members need to have implementation code in the interface.

Again, there is much to explore here, particularly around use cases and implementation.

Static Methods
What are the use cases for static methods in interfaces? I can imagine that we could have an interface that *only* has static methods. This could be a glob of functions that can be used independently of any class. How would this differ from a static class that only has static methods? There is a lot to explore here.

Update - Article Now Available: C# 8 Interfaces: Static Members.

Static Fields
This one is really new since interfaces could not contain fields before. But the real restriction is that interfaces cannot have instance data. And that is still true. Instance fields are not allowed, but we can have static data at the interface / abstraction level.

There is a tutorial on the Microsoft docs site (https://docs.microsoft.com/en-us/dotnet/csharp/tutorials/default-interface-members-versions) which shows how to use static fields as parameters for default implementation methods. This is an interesting use case. Are there other use cases for static fields?

Update - Article Now Available: C# 8 Interfaces: Static Members.

Static Constructors
Interfaces can now have static constructors. What are the use cases for this? Static constructors can only access static members of the interface, so they could be useful for "new"ing up a static field (for example, a static field that is a List<T>).

Are there other uses for static constructors?

Other Features
There are a few other features that go along with the main items above. These are also worth a closer look.

Abstract Members
I previously wondered about the "abstract" modifier that is now allowed in interfaces. I didn't understand since interface members are "abstract" by default. But in looking into it further, "abstract" can be useful in an interface inheritance scenario.

If a base interface has a default implementation for a member, it is possible for a derived interface to mark that member as "abstract". This would have the effect of hiding the default implementation.

This gets interesting in the class implementations because a class that implements the inherited interface also implements the base interface. The class would need to implement the abstract member to satisfy the contract, but this is definitely worth taking a closer look at.

And just because this is possible doesn't mean we should do it. Are there good use cases for this?

Partial Interfaces
Previously "partial" interfaces were not allowed. Partial classes allow us to spread a class across different files. I have not seen widespread usage of this feature, but there are a few scenarios where it is useful. Interfaces now support this same "partial" functionality. It's worth taking a closer look at this to see what types of scenarios would need this.

Static Main
Another thing that I found in the design proposal is that "static Main" is supported in interfaces. I have not yet looked at this, but it will be interesting to explore further.

Update - Article Now Available: C# 8 Interfaces: Static Main -- Why Not?
Update2 - Another article: Misusing C#: Multiple Main() Methods

Struct and Default Implementation
There is a "wart" [terminology from the proposal] when it comes to structs and default method implementation. The interface methods are not available in the struct the same way they are in a class. So to get to the default implementation, it requires boxing the struct. I have not seen a lot of structs that implement interfaces. And guessing from the decision to leave it like this, I suspect that the language designers have not seen much of it either. This is more a curiosity than something you're likely to need to deal with.

Lots to Explore
That's my list of things that need further exploration. I'll be diving into these as soon as I get the release bits of .NET Core 3.0 and the latest Visual Studio 2019 updates.

If you have any ideas for use cases mentioned above, or there are other areas that you'd like me to take a closer look at, be sure to leave a comment.

Be sure to check back because there's lots to explore.

Happy Coding!

Sunday, September 1, 2019

Interfaces in C# 8 are a Bit of a Mess

Interfaces are getting a significant overhaul in C# 8. I've been looking at some of the features, and I'm frankly stumped at some of the decisions that have been made. I'm also a bit disappointed at the messaging from Microsoft regarding these new features.

I'll start out by saying that I may be completely missing the point. So feel free to leave your comments. I'm looking for any help I can get at this point.

Code for this article (and further experimentation) is available on GitHub: jeremybytes/interfaces-in-csharp-8. Note: at the time of this writing, the code uses .NET Core 3.0 Preview 8.

Some of the new features include the following:
  • Default implementation for interface members
  • Access modifiers - public, private, protected, internal
  • abstract members
  • static members
Let's start by looking at default implementation.

Default Implementation of Interface Members
Default implementation has been the most widely-touted enhancement to interfaces in C# 8. Mads Torgersen wrote an article on the topic: https://devblogs.microsoft.com/dotnet/default-implementations-in-interfaces/. This article has the example that I've seen repeated when this topic is brought up.

The assumption is that we have an interface with a single member, and a class that implements that interface.

Then another member is added to the interface. To keep the existing implementations from breaking, we add default behavior to the new interface member.

Here is an ILogger interface that has 2 members. The second has a default implementation (this is in the ILogger.cs file in the GitHub project):


The original class only implements the first member (this is in the InitialLogger.cs file in the GitHub project):


Since the 2nd member (the Log method that takes an exception parameter) has a default implementation, this code builds just fine.

We can put together a little console application that shows that both methods work (this is in the Program.cs file in the GitHub project);


The output shows that calls to both of the Log methods work:


Of course, we are also free to provide an implementation of the 2nd member in the class. This would hide the default implementation.

My Thoughts
When I first heard of this feature, I thought it was a bad idea. This blurs the line between an abstract class (that contains implementation) and an interface (no implementation).

My recommendation would be to avoid default implementation for a few reasons.

First, I have only seen trivial examples where a good default exists. Most of our code is more complicated than that. If I want to add "Save" functionality to my API, there is probably no good default for that. If I end up throwing a NotImplementedException as a default, then that doesn't accomplish anything other than moving compile-time errors to run-time errors.

Second, we already have a way to extend functionality of an interface -- through interface inheritance. By creating a new "extended" interface that inherits from the original, the existing interface implementations continue to work. And if a client needs the extended functionality, then the client can use the new extended interface (this also helps us follow the interface segregation principle).

Third, interfaces are a difficult enough concept as it is. When I started programming professionally, it took me a good 2 years before I really understood interfaces and what they were good for. This was such a frustration to me that I've spent the last 7-1/2 years helping developers understand interfaces (this includes 33 live presentations, various blog articles, and a Pluralsight course that has over 100,000 unique viewers). If nothing else, this points out that the topic can be a challenge for developers to grasp.

Messaging from Microsoft
Most of the messaging from Microsoft has been around this -- adding functionality to an existing API. The idea that if you have an existing interface, you can add to it without breaking the initial implementations.

But it turns out that this is not the only reason this feature was added to the language.

For this, we can turn to C# 8 Language Design Proposals. Here is the article for default implementation: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/default-interface-methods.

There are 3 reasons stated for this change: (1) extending APIs, (2) interoperability with Android (Java) and iOS (Swift), (3) supporting the "traits" language feature.

"Traits" are really a way of doing mix-ins with classes. The idea is that small groupings of code can be combined to form classes.

I think that traits can be a good idea; however, I think that using interfaces to implement that feature is a mistake. Another construct in C# would be less confusing to developers (even if it compiles down to the same IL).

To show the confusion that's on its way, let's take a look at some of the other changes to interfaces that facilitate these features.

Access Modifiers
Previously, access modifiers were not allowed on interface members. Here's an example from a .NET Framework 4.7.2 project:


Previously, all interface members were automatically visible. We weren't even allowed to mark something as "public". If we think of interfaces as a contract, then it makes sense that we are not allowed to use access modifiers. The terms of the contract need to be visible to everyone -- both the clients and the implementing classes.

But things are different with C# 8. We can have access modifiers. Here's an example of an interface that has a "protected" member (this is in the IReader.cs file in the GitHub project):


This causes a bit of confusion when implementing the interface. Mainly because the tooling isn't there yet. (I'm hoping it will be there soon; .NET Core 3.0 releases in 3 weeks.)

If we create a new class and mark it with the interface, we get the standard errors that there are members that are not implemented:


Note: since the Save method has a default implementation, it does not show up with the missing members.

I use the Ctrl+. shortcut to implement interfaces (or use the light bulb helper):


This, however, only implements the non-protected member. So if we use this "fix" and try to build, we still get errors:


The protected member is still not implemented.

To implement the protected member, we need to do an explicit implementation. This associates the method explicitly with the interface. This is another option on the Ctrl+. menu:


But if we do this, it implements *both* of the methods explicitly:


Note: Regardless of whether we use "Implement interface" or "Implement interface explicitly". The Save method (which has a default implementation) is not included. If we want to override that behavior, we need to type that in ourselves.

Now we have 2 implementations for "GetItem": one associated with the class, and one associated with the interface. This is probably not what we want.

You can take a look at the IntReader.cs file in the GitHub project to see the implementation that is probably more inline with what we want in this case:


This is a tooling problem. It can be fixed in Visual Studio, but it opens the door to some of the other things that come up when we have access modifiers on interface members.

Private Members
Since we can add access modifiers to interface members, we can have "private" members.


[Update Note: This example is quite embarrassing since I added a "Save" method to an "IReader" interface. You shouldn't do this. At the time, I was experimenting with syntax and wasn't thinking about the interface itself. Then this article got a bit more popular than I was expecting. More well thought out articles are available here: A Closer Look at C# 8 Interfaces.]

In this code, the "Save" method is marked as "private". The compiler will only let you mark a member as "private" if it has an implementation. So that's good.

But what would we do with a private interface member? The answer is not much. It is not accessible outside of the interface, so it is really only good if we want to create a method that will be used in other default implementations in the interface.

At this point, we're really creating a class, and an abstract class would be a much better solution.

Abstract Members
The thing that make me go  O_o  is the fact that we can have "abstract" interface members. The following code is valid and builds (this is the final IReader.cs file from GitHub):


In this code, the "GetItem" method is marked as "abstract".

What does this even mean? When we're dealing with abstract classes, abstract members have a declaration but not implementation. That describes *everything* in an interface (okay, it described everything in an interface until we had default implementation).

I'm a bit confused by this. The code behaves the same way whether the "abstract" is here or not.

I'll need to do a bit more research to find out why this is necessary.

Static Members
Interfaces can also have static members. This is something that is brand new. Statics were not allowed at all in interfaces previously.

If you're curious about using static members in interfaces, take a look at the tutorial: Update interfaces with default interface members in C# 8.0. This example shows how static members can be used to parameterize default implementations.

My Thoughts
Static members break the spirit of interfaces. Interfaces have to do with describing a contract -- something that a client can rely upon being there and an implementer has to include. The tutorial shows using static fields to hold data. Those are now implementation details.

My Thoughts
In my view, interfaces in C# 8 are a bit of a mess. We can no longer think of them as a contract. They are no longer the "shape" of a set of members in a class or struct. Instead, they can contain implementation. The members are no longer automatically visible, they can be private, protected, or internal.

I may be completely missing the point. But I can no longer answer the question: "What is an interface?"

An interface is no longer one thing. It has multiple aspects depending on how we want to use it. It will take a while to make sense of the new world. If you want to share your views, please leave a comment. I'm looking for clarification and to gain a better understanding of the changes.

Update: More thoughts here (a bit more organized, too) - A Closer Look at C# 8 Interfaces.

Stay tuned to the GitHub project (jeremybytes/interfaces-in-csharp-8). There will be more samples added and more articles. Together we can figure this out.

Happy Coding!

Saturday, August 24, 2019

Converting .NET Framework to .NET Core - UseShellExecute Has a Different Default Value

I came across a difference between .NET Framework and .NET Core that caused a bit of frustration when I was converting a project.
Process.StartInfo.UseShellExecute defaults to "true" in .NET Framework, but it defaults to "false" in .NET Core.
If you have code using Process, this may come up when converting your projects over to .NET Core.

Discovery and Pain
.NET Core is the path forward. And I have been slowly converting my code from .NET Framework to .NET Core. This is especially interesting because I can now move my WPF projects over to .NET Core 3 (which will be released in about a month).

Yesterday, I was converting my maze generation program (GitHub: jeremybytes/mazes-for-programmers) and ran into an issue. This program generates a maze using a selected algorithm and outputs it as a text maze (using ASCII art) as well as a graphical maze (using a bitmap). The bitmap gets saved to the file system as a .png file.

The application itself is a console application, and I want to show the graphical maze after it is saved to the file system. So, I do a Process.Start to have Windows open up the file using the default bitmap viewer. Here is the code for that (code can be found in Program.cs of the DrawMaze project):


This works fine with .NET Framework. But when I ran it in .NET Core, I got a runtime exception.


"System.ComponentModel.Win32Exception; 'The specified executable is not a valid application for this OS platform.'"

This left me scratching my head.

There was something wrong with the Process.Start. This is not something I do regularly, but I do know that "StartInfo" has a lot of properties. So I started fumbling around looking for answers.

Google & StackOverflow were not very helpful -- probably because I didn't know what to search for.

One thing I tried was changing the file name to ".\maze.png". You need to use a ".\" in PowerShell to execute something, so I thought maybe I needed it here. That didn't work.

Another thing I tried was changing the "FileName" property to "cmd.exe" and adding an "Argument" property that had "maze.png". That didn't work.

Then I started looking through the docs for Process and more specifically StartInfo.

UseShellExecute
Eventually, I ended up at the "UseShellExecute" property (docs) and found this little gem:


"The default is true on .NET Framework apps and false on .NET Core apps."

o_O

As soon as I saw this, I knew it was my problem. This property determines whether to use the operating system shell to start a process.

When it is "true", it's basically the same as typing "maze.png" from a command prompt. If you do this from a Windows command prompt, it will will try to open the file using the default image viewer.

But if it is "false", then we're saying "execute this file", and a bitmap is not an executable.

Fixing the Code
The code fix was easy after that. I just had to set the UseShellExecute property to "true":


Then the program worked. On my machine it opens the "Photos" app, which is my default viewer.


(And in case you're curious, here's the full image of the maze that was generated -- be sure to zoom in to see all the interesting detail)


Cross-Platform Solution?
I find the cross-platform features of .NET Core to be particularly interesting. So I've been trying a bunch of my .NET Core projects on MacOS and on Linux.

I have not figured out how to do something like this in a cross-platform-friendly way. The text maze generation in a console/terminal window works just fine. The bitmap is created and saved to the file system just fine. But I'm not sure how to display the bitmap file automatically. I'm really relying on the default Windows behavior in the current application.

One potential solution is to put in some OS-specific code. If it is Windows, do a shell execute. If it is MacOS, open up the "Preview" application with the bitmap file. But there's really no equivalent in the Linux world. What I'd like to do is "open this bitmap with the default bitmap viewer". That doesn't exist on Linux.

Another idea is to open the file in a browser. But there's no guarantee that a particular browser is available on a particular platform.

If you have any ideas, be sure to leave a comment on this article.

Wrap Up
I really like .NET Core, and I'm excited for the Core 3 release so I can start using it with my WPF application on Windows.

.NET Core is the path forward. So far, moving code over to new projects has been fairly painless. But I have run into a few issues like this one that are a bit frustrating. This is a breaking change between platforms.

I did not run this application through the .NET Portability Analyzer. This application is small and straight forward -- a console application and a couple of libraries that aren't doing anything exciting; they don't even use any external NuGet packages. I should probably run it through the analyzer to see if it finds this change between the platforms.

I'll be sure to post any other strangeness I find when doing my conversions. And I'm hoping to do a walkthrough of an entire application conversion sometime soon.

Happy Coding!

Monday, July 1, 2019

Linking Files in Visual Studio

Linking files in Visual Studio lets us use the same physical file in different projects. I always forget how to do this, so I'm making notes here.

The Short Version
If you already know about linking files and why you want to do it, here's the short version that has the mechanics (details are further down).

To link files, use the "Add Existing Item" dialog. One way of getting to this is to right-click on the project and choose "Add", then "Existing Item...".


When the dialog opens, locate the file you want to link to.


Then DO NOT CLICK THE "Add" BUTTON. Instead, notice that the "Add" button is a drop-down (this is really easy to overlook).


Use the drop-down and select "Add As Link".

That's all there is to it!

If you want details on what linking files really means and why you might want to do it, keep reading.

The Long Version
To show the differences between copying files and linking files, I've set up a solution with 3 class libraries.


The first library, "A-SourceLibrary", is a .NET Core 3.0 class library that contains the file we want to use in the other projects. The file is called "Person.cs".

The file system shows that we have a .csproj file and one .cs file:


The second library, "B-CopiedFiles", is a .NET Standard 2.0 class library that does not currently have any files.

The file system shows that we have a .csproj file only:


The third library, "C-LinkedFiles", is a .NET Framework 4.7.2 class library that does not currently have any files.

The file shows that we have only a .csproj file here as well:


Let's look at the difference between copying and linking.

Copying Files
Copying files from one project to another is out in the open (for the most part).

Copy/Paste
As one option, we can right-click on the source file and choose "Copy" and then right-click on the destination project and choose "Paste".

The keyboard shortcuts Ctrl+C and Ctrl+V also work as long as you have the correct items selected in the Solution Explorer.

Add Existing Item
Another way to copy a file is to Add an Existing Item. We will do this to copy the "Person.cs" file from the "A-SourceLibrary" project to the "B-CopiedFiles" project.

Just like above, you right-click on the project, and select "Add", then "Existing Item..."


When the dialog pops up, just locate the file.


And then click the "Add" button.

This will create a *copy* of the file in the destination project. We see the new file pop up in the Solution Explorer.


But we also see a new file pop up in the File Explorer for the project.


Now we have 2 separate copies of the "Person.cs" file. If we make changes to one file, it will not be reflected in the other.

If we only want 1 physical file that appears to multiple projects, we can use a linked file instead.

Linking Files
The problem I always have with linking files is that I forget how to do it. When I copy files from one project to another, I usually do the "Copy"/"Paste" options that show up in the right-click menu (or with the keyboard shortcuts).

When I want to link a file, I copy the file to my clipboard and the look for a "Paste Special" or something similar on the right-click menu. That doesn't exist. Then I have to try to remember how to do it. So here it is.

This time we will link to the "Person.cs" file in the "A-SourceLibrary" project in the "C-LinkedFiles" project.

As we saw above, we just need to right-click on the destination project ("C-LinkedFiled") and choose "Add" then "Existing Item..."


Then in the dialog, locate the source file in the "A-SourceLibrary" folder.


Then use the drop-down on the "Add" button to choose "Add As Link".


This adds a link to the file in the destination project. We can see that the "Person.cs" file shows up as part of the "C-LinkedFiles" project in Visual Studio.


But if we look at the file system, the "C-LinkedFiles" folder does *not* have a "Person.cs" file.


When we look at the Solution Explorer, we can see that there is a different icon for the linked file compared to the copied file (and the original file):


What we have done is create a reference in one project to a file in a different project. So if we make changes in one location, it is reflected in both.

Why Would We Want to Link Files?
So why would we want to do this? Usually if we want to use an existing class, we would reference that assembly and use it directly. This avoids duplication. And this is what I do when I can.

But in this scenario, we have 3 different class libraries all with different targets. In this case, we may not be able to reference one assembly from another. This example is a bit contrived, so let's explore something a little more realistic.

Transitioning to .NET Core
We are in a bit of a transition period with .NET. As of today, .NET Core 3.0 is still coming (it will be released on September). With .NET Core 3.0, we also get .NET Standard 2.1.

But most people have a lot of applications that are .NET Framework. If I have a .NET Framework 4.7.2 project, I will not be able to use a .NET Standard 2.1 library (only .NET Standard 2.0). While I'm moving my projects from .NET Framework 4.7.2 to .NET Core 3.0, I may want to set up some interim projects to help with the transition.

So I could create a .NET Standard 2.1 class library with the intention that this will be the library referenced by the .NET Core 3.0 project. And then I can create a .NET Standard 2.0 project (that links to the files in the .NET Standard 2.1 project) that I can use today with the .NET Framework project.

For anything that doesn't match up (for example, I might be using additional APIs in the .NET Standard 2.1 project -- like Task.IsCompletedSuccessfully), I can copy files and make custom shivs that will get me through the transition period.

Shared Libraries
Another place where linked files can come in handy is if we create shared libraries (or NuGet packages) that will be used in different environments. We may need code that is a bit different for each environment, but we can use linked files to share what we can.

WPF on .NET Core 3.0
Another place this is useful is when transitioning WPF from .NET Framework to .NET Core. Right now, the WPF designers in Visual Studio are not quite complete for .NET Core. (I'm hoping things will be awesome when it comes to release time.)

To help with the transition, we can have *both* a WPF .NET Framework project and a WPF .NET Core project. We can put our production forms (XAML) in the .NET Core project and link the files to the .NET Framework project.


Then we can use the XAML designer in the .NET Framework project and build/run the .NET Core project.

We only have one set of files to worry about.

Linking Files is Useful
Linking files is really useful. I used to do this quite a bit back in the Silverlight days (boy, I feel old now). Each class library would link to the same source files (sometimes with #if/#endif directives for conditional compilation).

When I got started experimenting with WPF on .NET Core 3.0, someone gave me the advice to link files to get the designers like mentioned above. That was great except that I completely forgot how to link files. So I dropped this here mainly for me to remember later.

Keep learning, and find somewhere to log the things you forget. Then you will have them available to you the next time.

Happy Coding!

Tuesday, April 2, 2019

Task.IsCompletedSuccessfully - YAY! (and hmmm)

So, apparently I missed something along the way. Task in C# has an "IsCompletedSuccessfully" property (in some environments). This has been around since .NET Core 2.0, and it is in the current 2.2 release (and the 3.0 preview).
The reason I love the idea of "IsCompletedSuccessfully" is that "IsCompleted" does not mean what you think it means.
But there are some caveats about which types of projects can use this property. More on that below.

The Problem of "IsCompleted"
I've been writing and speaking about Task and Await since 2015. It's one of those things that took me a while to understand and then became really useful to me.

One of the hurdles I had to deal with has to do with the "Is" properties on Task. These include "IsCanceled", "IsFaulted", and "IsCompleted".


The main problem with these properties is that they sound like they are mutually exclusive, meaning something will be *either* Canceled *or* Faulted *or* Completed. And that is not the case.

If we look at the documentation for "IsCompleted", we find the following remarks:


IsCompleted will return true when the task is in one of the three final states: RanToCompletion, Faulted, or Canceled.

So "IsCompleted" does not mean "completed successfully", it means "no longer running".

The usefulness of this property in Task continuations is limited. And because of the problems I had when I first came across it, I have talked about it in articles (Task Continuations), videos (Task and Await in C# - Part 3), and also in my live presentations (I'll Get Back to You: Task, Await, and Asynchronous Methods).

Note: the short version is that if we want to see if a Task completed successfully, we can use the Task.Status property (an enumeration) and look for "RanToCompletion".

With .NET Core 2.0 and later, we finally get the option that I've been waiting for.

IsCompletedSuccessfully
The "IsCompletedSuccessfully" property has been around since .NET Core 2.0. Somehow I missed it. It wasn't really a surprise that I missed it because I was mainly using Task in WPF projects (.NET Framework) and .NET Standard 2.0 class libraries. This property is not available in those environments (more on that in a bit).

First, let's look at the documentation (Task.IsCompletedSuccessfully Property):


The first thing to note is that the documentation is currently incomplete. It just tells us that the property exists, but it doesn't say what it is for. Based on previous experience (and a little experimentation), we can deduce that this tells us whether the task ended up in the "RanToCompletion" status.

Also note that this applies to .NET Core only. It has been available since .NET Core 2.0, and it is available in 2.1, 2.2, and the 3.0 Preview.

So, Yay! that this is available, and hmmm... let's figure out where we can really use this.

.NET Core vs. .NET Standard
The first thing to consider is that there is a difference between .NET Core and .NET Standard. With .NET Standard, we can create libraries that will compile in a variety of environments. I have created lots of .NET Standard libraries that can be used with WPF applications (using .NET Framework) and WebAPI applications (using .NET Core).

This is great because .NET Standard gives us a standard set of APIs that can be used by any project that supports that version of .NET Standard.

I've been using .NET Standard 2.0. This means that my libraries will work with .NET Core 2.0 (and above) and .NET Framework 4.6.1 (but more realistically, they work with .NET Framework 4.7.2 -- but that's another story).

The bad news is that "IsCompletedSuccessfully" is *not* available in .NET Standard 2.0.

This means that for my current projects using .NET Standard 2.0 and WPF with .NET Framework 4.7.2, this property is not available.

If we do want to use "IsCompletedSuccessfully" in a class library, we also have the option of creating a .NET Core class library. This has the restriction that we can only call it from a .NET Core project, so it will not work with a .NET Framework project like our .NET Standard libraries do.

The good news is that "IsCompletedSuccessfully" *is* available in .NET Standard 2.1.

It's important to understand that .NET Standard 2.1 is not really available yet. This will come along with .NET Core 3.0 which is still in preview.

To make things more "interesting", .NET Standard 2.1 will not be supported by .NET Framework 4.8. Here's an excerpt from Microsoft: "Announcing .NET Standard 2.1".
"Given many of the API additions in .NET Standard 2.1 require runtime changes in order to be meaningful, .NET Framework 4.8 will remain on .NET Standard 2.0 rather than implement .NET Standard 2.1. .NET Core 3.0 as well as upcoming versions of Xamarin, Mono, and Unity will be updated to implement .NET Standard 2.1."
So, we will not be able to use this property with .NET Framework 4.8.

Can I Use "IsCompletedSuccessfully"?
  • .NET Core 3.0: YES
  • .NET Standard 2.1: YES
  • .NET Core 2.0+ : YES
  • .NET Standard 2.0: No
  • .NET Framework 4.7.2: No
  • .NET Framework 4.8: No

Moving to .NET Core 3.0
With all of the changes that are happening in the .NET ecosystem, it is becoming more and more clear that we should be moving to .NET Core. For 2 examples, (1) .NET Framework 4.8 will not support .NET Standard 2.1, and (2) several C# 8 features will not be implemented in .NET Framework 4.8.

.NET Core 3.0 supports WinForms and WPF applications. I've done a few experiments with the Preview of .NET Core 3.0, and it works pretty well for the WPF applications that I've converted.

If we start to move to .NET Core, then things get easier in a lot of areas. The project systems are more compatible, we get runtime enhancements, and we can use .NET Standard 2.1.

We are in bit of a transitional period here. .NET Core 3.0 is still to be released. And even though Visual Studio 2019 works well with the .NET Core 3.0 Preview, the tooling for WinForms and WPF does not exist yet. There are some ways that we can manage WPF projects today, and I'll show that in an upcoming article.

If you haven't done so already, take a look at .NET Core. This is the future of .NET.

Happy Coding!