Category Archives: Programming

CommunityToolkit.Mvvm “already contains a definition for” error

The CommunuityToolkit.Mvvm includes a wonderful MVVM source generator, but in the current .NET 6.0 release I’m using, (doesn’t happen with MAUI but does with WPF) I get errors such as

  • The type ‘MyViewModel’ already contains a definition for ‘MyProperty’
  • A partial method may not have multiple defining declarations

To fix this (at least in the current version of .NET 6.x) add a global.json file to the folder with your solution file

{
  "sdk": {
    "version": "6.0.202",
    "rollForward": "disable"
  }
}

and things should work correctly – hopefully this post will be obsolete soon with the issue fixed, but for now this solves the problem.

WPF UserControl DependencyProperty Binding

On the weekend I was messing around creating a simple WPF card game application and wanted to just quickly knock together a UserControl with a dependency property (actually there were several controls and several dependency properties) which allows the hosting Window or UserControl to change the property.

Ofcourse we should probably look at implementing this as a lookless control but I was just trying to do the bare minimum to get this working as a proof of concept.

So what I want is UserControl which displays playing card, so let’s call it CardView and it looks like this (excluding the UserControl element for brevity)

<Grid>
   <Border Background="White" Padding="8" CornerRadius="8">
      <Image Source="{Binding CardImage, RelativeSource={RelativeSource AncestorType=UserControl}}"/>
      <Border.Effect>
         <DropShadowEffect />
      </Border.Effect>
    </Border>
</Grid>

and the code behind looks like this

public partial class CardView : UserControl
{
   public static readonly DependencyProperty CardImageProperty = DependencyProperty.Register(
      nameof(CardImage), typeof(Uri), typeof(CardView), new PropertyMetadata(default(Uri)));

   public Uri CardImage
   {
      get => (Uri)GetValue(CardImageProperty);
      set => SetValue(CardImageProperty, value);
   }

   public CardView()
   {
      InitializeComponent();
   }
}

The key thing here is that we have this code-behind dependency property CardImage, and in the XAML we want to show the image of the card that was set through the dependency property.

If this was a lookless control we’d have set this binding up like this

RelativeSource={RelativeSource TemplatedParent}

but there’s no separation here of style and code, instead everything’s in the UserControl, so we have to use

RelativeSource={RelativeSource AncestorType=UserControl}

This will then bind the UserControl Image to the dependency property in code-behind and allow our host Window or UserControl to simply do the following

<local:CardView Width="140" Height="200" 
   CardImage="../Resources/HQ.png"/>

For this example, the png’s will be stored in a Resources folder with their Build Action set to Resource.

.NET HttpClient – the correct way to use it

For ages I’ve been using the HttpClient in .NET without any issues, but usually I have a single endpoint and a singleton (or equivalent) of a class that uses the HttpClient. A while back I needed to call multiple different endpoints using the HttpClient and so I happily wrapped an instantiation of an HttpClient in a using statement, I mean after all it has an IDisposable interface so that makes sense right?

Well NO this is not the case. So don’t do this!

// Don't do this
using(var httpClient = new HttpClient())
{
   // do something with httpClient
}

This post stems from a work colleague pointing me to the post YOU’RE USING HTTPCLIENT WRONG AND IT IS DESTABILIZING YOUR SOFTWARE.

What does the documentation say?

If you take a look at the HttpClient Class documentation states

HttpClient is intended to be instantiated once and re-used throughout the life of an application. Instantiating an HttpClient class for every request will exhaust the number of sockets available under heavy loads. This will result in SocketException errors.

If we take a look at some C# templates in Visual Studio, for example the ASP.NET core Blazor application template, it will give you a scoped instance of the HttpClient, for example

builder.Services.AddScoped(sp => 
  new HttpClient 
    { 
       BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) 
    }
);

So how are we supposed to use a single instance of HttpClient

Let’s now assume that we create an HttpClient per application. Then how do we call multiple service endpoints without having changes affect different endpoint calls and is it threadsafe?

Is the HttpClient thread-safe? Well the answer is both yes and no.

Changing properties on the HttpClient are not threadsafe or at least cannot/should not be modified whilst there are outstanding requests. However methods such as GetAsync, PostAsync, SendAsync etc. are threadsafe which then leads us to how to se set-up different calls, i.e. maybe different headers etc. on all our calls. The answer here is to use SendAsync and create an HttpRequestMessage. This allows us to specify many of the properties we’ll need per HTTP call.

References

YOU’RE USING HTTPCLIENT WRONG AND IT IS DESTABILIZING YOUR SOFTWARE
HTTPCLIENT CREATION AND DISPOSAL INTERNALS: SHOULD I DISPOSE OF HTTPCLIENT?

Nullable reference types in C#

Nullable reference types are now enabled by default on projects created with Visual Studio 2022, so let’s have a quick look at them…

Enabling nullable reference type checking

By default nullable reference types were disabled prior to Visual Studio 2022, so would need enable them at a project or file level. Enabling in the project means adding the following to the .csproj file

<PropertyGroup>
  <OutputType>Exe</OutputType>
  <TargetFramework>net5.0</TargetFramework>
  <Nullable>enable</Nullable>
</PropertyGroup>

If you prefer to enable at a file level then simply add the following to the top of each file

#nullable enable

Now what?

So once you’ve enabled nullable reference type checking, especially if on a legacy code base, be prepared for warnings such as

  • warning CS8625: Cannot convert null literal to non-nullable reference type.
  • warning CS8604: Possible null reference argument for parameter ‘s’ in ‘void Program.SetName(string s)’.
  • warning CS8602: Dereference of a possibly null reference.

I’m sure there are plenty of other warnings, but you get the idea.

Basically what we’re ask the compiler to do is tell us when we might have the potential to be passing a null into a function etc. and highlight the potential issue with a warning. In other words we now need to mark reference types as nullable so the compiler knows we’re expecting a null and in situations where we’re not using a nullable reference type we’ll be warned.

Let’s see some example code. First off, if you default arguments to null, for example

public void SetName(string name = null)
{
   // do something
}

This will result in the warning >warning CS8625: Cannot convert null literal to non-nullable reference type.. All we need to do is tell the compiler we’re expecting a null, by making the argument nullable, i.e. add the ? to the type just like nullable value types.

public void SetName(string? name = null)
{
   // do something
}

Any usage of the variable name will now expect a null check, so if we compile the following

public void SetName(string? name = null)
{
   Console.WriteLine(name.Length);
}

as you’d imagine, the compiler will issue a warning here, in this case warning CS8602: Dereference of a possibly null reference., so obviously we have the potential of a null reference exception here, so adding a conditional check like this will fix that

static void SetName(string? name = null)
{
   if (name != null)
   {
      Console.WriteLine(name.Length);
   }
}

In some situations you may in fact know a variable/argument is not null – in TypeScript it’s not unusual to find the transpiler getting a little confused in which case we use the null-forgiving operator simply an !, so whilst the SetName method, as it stands ofcourse can be null, what if we remove the optional argument and expect all callers of the SetName method – for example maybe it’s a private method and we know each caller must check for null first anyway, then we use the following

static void SetName(string? name)
{
   Console.WriteLine(name!.Length);
}

We’re basically saying, by using name!. we know the value is not null. This example is a little contrived because we could just change the string? to string and not require the !, but you get the idea.

Struct, Class and now Record types in C#

I thought it’d be interesting to compare the three C# types, struct, class and record. I’m sure we all know that a struct is a value type and a class a reference type, but what’s a record.

The record “keyword defines a reference type that has built-in functionality for encapsulating data” (see Records (C# reference)).

Before we get into record. let’s review what struct and classes give us using the example of a Person type which has a FirstName property.

struct

struct Person
{
  public string FirstName { get; set; }
}
  • A struct extends System.ValueType and structs are “allocated either on the stack or inline in containing types and deallocated when the stack unwinds or when their containing type gets deallocated. Therefore, allocations and deallocations of value types are in general cheaper than allocations and deallocations of reference types.” See Choosing Between Class and Struct.
  • ToString() will output YouNameSpace.Person by default.
  • Structs cannot be derived from anything else (although they can implement interfaces).
  • Structs should be used instead of classes where instances are small and short-lived or are commonly embedded in other objects.
  • As structs are ValueTypes they are boxed or cast to a reference type or one of the interfaces then implement.
  • As a function of being a ValueType, structs are passed by value

class

class Person
{
  public string FirstName { get; set; }
}
  • A class extends System.Object and classes are reference types and allocated on the heap.
  • ToString() will output YouNameSpace.Person by default.
  • Obviously classes may extend other class but cannot extend a record and vice versa, records cannot extend classes.
  • Reference types are passed by reference.

record

Records can have properties supplied via the constructor and the compiler turns these into readonly properties. The syntax is similar to TypeScript in that we can declare the properties in a terse syntax, such as

record Person(string FirstName);

Whilst records are primarily aimed at being immutable we can still declare them with mutability, i.e.

class Person
{
  public string FirstName { get; set; }
}
  • Records can only inherit for other records, for example
    record Scooby() : PersonRecord("Scooby");
    
  • Records use value comparison (not reference comparison) via IEquatable
  • ToString formats output to show the property values
  • Records support the with keyword which allows us to create a copy of a record and mutate at the point of copying. Obviously as records are generally aimed at being immutable this use of with allows us to copy an existing record with some changes, for example
    var p = somePerson with { FirstName = "Scrappy" };
    

    This is not a great example with our record which has a single property, but if we assume Person also had a LastName property set to “Doo” then we’d essentially have created a new record with the same LastName but now with the new FirstName of “Scrappy”.

    We can also copy whole records by not supplying any values within the { } i.e.

    var p = somePerson with { };
    

More Pattern Matching in C#

A while back I wrote a post C# 8.0 enhancements with pattern matching which was very light on the subject. Let’s look a little more in depth at options for pattern matching.

is/as in pattern matching syntax

Often (if you’ve been writing C# for a while) you’ll used to writing code like this

var person = o as Person;
if (person != null)
{
   Console.WriteLine(person.FirstName);
}

i.e. we have an object o which we don’t know the type of, so we use as to convert this to a Person type or null if it’s not of that type.

This can be replaced with a slightly more concise syntax (and what’s known as the declaration pattern).

if (o is Person person)
{
  Console.WriteLine(person.FirstName);
}

Null checks

This is a pattern known as a constant pattern

if (o is null)
{
  Console.WriteLine("Is null");
}

Along with a logical pattern using not we can also write

if (o is not null)
{
  Console.WriteLine("Is not null");
}

We can also use this pattern with types, for example

if (o is not (string or null))
{
  Console.WriteLine("Is NOT string or null");
}

<strong>Pattern matching when values match a criteria</strong>

If we extend the above Pattern Matching to not just check the type is a Person but also that the Age property is greater than 4, so we can now replace

[code language="csharp"]
if (o is Person p && p.Age > 4)
{
  Console.WriteLine($"Older than 4 {p.FirstName}");
}

with the following

if (o is Person { Age: > 4 } p)
{
   Console.WriteLine($"Older than 4 {p.FirstName}");
}

In the above we’re using a property pattern.

Switch patterns matching

Exhaustive switches can be used to match types using switch statements, for example

var result = o switch
{
  string s => $"String {s}",
  Person p => $"Person {p.FirstName}",
  _ => throw new ArgumentException("Unhandled type")
};

Note the use of the _ (discard) ensuring this is an exhaustive switch.

Better still we can also use other features of pattern matching in the switch like this

var result = o switch
{
  string s => $"String {s}",
  Person { Age: > 4} p => $"Person {p.FirstName} > 4",
  Person p => $"Person {p.FirstName}",
  null => "In Null",
  _ => throw new ArgumentException("Unhandled type")
};

In the above we’re switching based upon type and also matching values.

We can also use relational patterns, in this example we’ll assume o is an int

var result = o switch
{
  1 or 2 => "One or Two",
  > 2 and < 4 => "Mid",
  >= 4 and < 6 => "High",
  6 => "Six",
  _ => "Other"
};

Before we leave the switch statement we can also match against types using the “standard” switch syntax, i.e.

switch (o)
{
  case string s:
    Console.WriteLine(s);
    break;
  case Person p:
    Console.WriteLine(p.FirstName);
    break;
}

Tuples

Pattern matching also allows us to match against tuples and use the discard to ignore parts we’re not interested in, for example

var result = o switch
{
  (1, _) => "First One",
  (_, 0) => "Second Zero",
  _ => "Other"
};

Creating new variables from patterns

We can also use the var pattern to assign values from the patterns

var result = o switch
{
  var (a, b) when a < b => new Tuple<string, int, int>("First less than second", a, b),
  var (a, b) when a > b => new Tuple<string, int, int>("Second greater than first", a, b),
  var (a, b) => new Tuple<string, int, int>("Equals", a, b)
};

In this example we’re deconstructing a tuple and assigning to some new value (in this case an extended Tuple, just because I couldn’t think of a better example – check the documentation link above for a better example).

Mocking – JustMock Lite, NSubstitute, FakeItEasy and Moq

I having been working on several projects with different teams, each have their preferred mocking framework (as well as many other differences in choices of tech.), this post is not meant as a comparison of popularity, preference or even functionality, its really more of a reminder to myself how to use each framework for the core mocking requirements so when switching between teams/projects I’ve a little reminder of the different syntax etc.

Note: This post is not complete or particularly comprehensive and I’ll update further as I need to use other features of the various libraries, but just wanted to get this published before I forget about it. Also there may be better or alternates ways to do things in different frameworks, for the purpose of this post I’m only really interested in showing the bare minimum changes to switch between frameworks.

Please note, MOQ version 4.20 has introduced a SponsoreLink which appears to send data to some third party. See discussions on GitHub.

What are we mocking?

Before we get into the details of the Mock frameworks, let’s see what we’re mocking

public interface IDataProvider
{
  IList<string> GetIds(string filter);
  event EventHandler Updates;
}

So let’s assume this will be an interface to some data provider, whether it’s remote or what the implementation is makes no difference, but the premise is we get some data using GetIds – maybe a list of trades in a trading application. The event tells us there have been updates to the data (this is a rather simplistic example as we don’t tell the consumer what the updates are, but you get the idea hopefully).

We’ll be passing the IDataProvider into a class which will act like a repository and will be used to get the data specific to that repository and the likes, the implementation of this is not really important to the specifics of this post and hence not included here.

Arrange, Act and Assert (AAA)

AAA is a pattern used within unit tests to

  • Arrange – initialize code including setting up any requirements for the system under test, i.e. create instances of objects to be tested, initialize values of the system under test etc.
  • Act – this is really just the action of using the code that we’re testing
  • Assert – this is the stage where we assert or verify results, i.e. did the system under test return the expected data/value

In terms of mocking frameworks, these should also follow and allow a similar flow when used. What we’re after is a way to create instances of

Arrange

To arrange our mock (or unit tests in general) we aim to create the component parts of a test and setup methods regarding what happens when they’re called etc.. In the case of using a mocking framework, we’ll use the framework to create instances of interfaces (or actual objects in some cases) and as the methods on an object don’t really have implementations behind them, we will want to declare what happens when code tries to call our mocked methods.

JustMock

var provider = Mock.Create<IDataProvider>();

Mock.Arrange(() => provider.GetData("/trades")).Returns(tradeData);

Moq

var provider = new Mock<IDataProvider>();
// or
var provider = Mock.Of<IDataProvider>();

provider.Setup(instance => 
   instance.GetTrades("/trades")).Returns(tradeData);

NSubstitute

var provider = Substitute.For<IDataProvider>();

provider.GetTrades("/trades").Returns(tradeData);

FakeItEasy

var provider = A.Fake<IDataProvider>();

A.CallTo(() => provider.GetTrades("/trades")).Returns(tradeData);

Act

The Act phase is actually the use of our mock objects as if we’re calling the actual implementation, hence in our code we may actually call

provider.GetTrades(route);

See also the section on events to see the mocking frameworks calling events.

Assert

In the unit tests we would now assert the results of our system under test, this may take a form such as of an NUnit assert, such as

Assert.AreEqual(3, systemUnderTest.Trades.Count);

This isn’t really part of the mock, as by this time hopefully our mock objects and methods have been called but we might wish to verify that the calls to the mocked methods actually happened.

Verify

In cases where you wish to assert that a mock has been called correctly, i.e. with the correct arguments or it’s been called N number of times, then we need to Assert. Assertions may be quick complex, for example we might want to ensure that a mock was only called with specific arguments, was called once or many times, maybe we don’t care about the arguments etc.

Let’s look at a fairly simple example where we want to ensure our mocked method is called once and once only

Note: JustMock includes the expectations of call occurrences etc. when arrange the mock hence we just verify or in JustMock, Assert, that all the previous Arrange definitions have been met.

JustMock

Mock.Assert(provider);

Moq

provider.Verify(instance => instance.GetTrades("/trades"), Times.Once());

NSubstitute

provider.Received(1).GetTrades("/trades").

FakeItEasy

A.CallTo(() => provider.GetTrades("/trades")).
   Returns(tradeData).MustHaveHappenedOnceExactly();

What about exceptions?

In some cases we want to mimic the mocked code throwing an exception, we do this as part of the Arrange phase on all frameworks

JustMock

Mock.Arrange(() => provider.GetIds("/trades"))
   .Throws<ArgumentNullException>();

Moq

provider.Setup(instance => instance.GetIds("/trades"))
   .Throws<ArgumentNullException>();

NSubstitute

provider.GetIds("/trades").Returns(x => throw new ArgumentNullException());

FakeItEasy

A.CallTo(() => provider.GetIds("/trades")).Throws<ArgumentNullException>();

What about events?

Ofcourse C# has an event model which we would also want to mock, let’s see how each framework allows us to simulate events. The Mock framework would already have supplied the event code and hence what we’re really wanting to do it cause an event to occur. This would therefore be part of the Act phase

JustMock

Mock.Raise(() => provider.Updates += null, null, null);

Moq

provider.Raise(instance => 
   instance.Updates += null, EventArgs.Empty);

NSubstitute

provider.Updates += Raise.Event();

FakeItEasy

provider.Updates += Raise.WithEmpty();

Code

Code is available on GitHub

Index and Range in C#

In C# 8.0 two classes were added to C# to handle Index and Ranges (as well as some syntactic sugar in the form of .. to represent a Range). Both are structs, an Index being literally an int but with some static method and “helper” methods for using indicies. As you might expect, a Range, is made up of a start Index and an end Index. Let’s have a look at both types in a little more depth…

Index

An Index is a very simply type which is best understood in usage on a collection. Let’s therefore assume we have some collection type which, ofcourse, allows for you to get at item at a specific index.

This is hardly an exciting addition in itself but what it does is gives us some “standard” code for handling things like, get the nth item from the end of the collection, using the overloaded ^ operator. Let’s see this in action by creating a simply collection

public class MyCollection
{
  private readonly string[] _collection;

  public MyCollection()
  {
    _collection = new[]
    {
      "One",
      "Two",
      "Three",
      "Four",
      "Five"
    };
  }

  public string this[Index idx] => _collection[idx.GetOffset(_collection.Length)];
}

All we’ve really done here that’s slightly different to how we’d have written this without an Index is we use the Index GetOffset to give us the actual index number to get the value from the collection. What this really does is allow us to write code such as

var c = new MyCollection();
Console.WriteLine(c[^2]);

The ^2 on an Index simply means give me the 2nd item from the end which would result in “Four” being written to the console ^1 would be the equivalent of _collection[_collection.Length – 1] hence you can see that ^2 is the equivalent of _collection[_collection.Length – 2]. The Index helper method simply allows us to let it handle any conversion for us. Ofcourse we can write the following

var c = new MyCollection();
Console.WriteLine(c[2]);

Which, as you’ve expect returns “Three” this item at index 2.

Range

The Range uses Index types to create a Range, for example

var range = new Range(1, 10);

This create a range type with a start of 1 and end of the range 10. Where the Range becomes more useful is in the syntactic sugar, the range shown in the snippet above may be written as

var range = 1..10;

This create a new Range type just as the first snippet, but now if we start to use this sort of stuff in collection types or our own types we start to get some neat syntax to get slices of collections – it should be noted that the current implementation of collections in .NET sees arrays supporting Range and hence can return slices of arrays, whereas other collections do not explicitly support Index and Range but instead can be used with them due to the operator overloading etc.

ofcourse we can create our own types to do similar. Before we look at implementing such things let’s quickly review the basic syntax possibilities/expectations

// short cut for getting a slice [0..10]
var firstToN = array[..10]; 
// short cut for getting the item 2 from the end
var nthItemFromEnd = array[^2]; 
// short cut for getting all items into a copy of the array
var all = array[..]; 

Support for Index

We can write our own types to explicitly understand Index and Range types, however using standard methods existing types can support Index and Range. Let’s demonstrate this by changing our MyCollection type to replace the indexer to look like this (i.e. remove the Index support).

public string this[int idx] => _collection[idx];

If you try to compile with myCollection[^2] you’ll now get a compiler error, cannot convert from ‘System.Index’ to ‘int’. So how do existing types work with Index? This is due to “implicit Index support” which basically means the compiler expects certain named methods with certain expected parameters.

The first required is the type is Countable which basically means it has a property named Length or Count with an accessible getter which returns an int. So this covers arrays and collections such as the List type. Let’s therefore add this to our type

public int Count => _collection.Length;

Now the compiler error will go away. If you think about it, it quite obvious what’s happening, in our original code for the indexer

public string this[Index idx] => 
   _collection[idx.GetOffset(_collection.Length)];

We ofcourse need the length of the collection as well as the Index. Well the compiler using the “implicit Index support” needs the same. So once we add the Count or Length properties, it can now get that information at create the code we otherwise would have to write ourselves and thus an indexer [int idx] now gets the value from the Index implicitly supplied.

So to wrap up “implicit Index support”, your type needs the following

  • The type is Countable i.e. has Length or Count property accessible and returning an int
  • The type has an accessible indexer which takes an int
  • The type does not have an accessible indexer which takes an Index as the first parameter

Support for Range

Let’s change our calling code to try to get a slice of our collection, so now we have

var c = new MyCollection();
Console.WriteLine(c[1..^2]);

This will immediately show the compile time error “cannot convert from ‘System.Range’ to ‘int'”. Let’s therefore add implicit support for Range to our collection.

Well again the type needs to be Countable and also not have a accessible indexer which takes a Range (otherwise this would assumer the type is explicitly handling Range). Which currently have.

As you’d imaging to handle ranges we need a method that creates a slice or sub-collection from our collection and that’s exactly what’s required. Let’s add a Slice method which returns a collection (in our case we’re just pretty much copy the code from Ranges which is also the best place to look for information on Index and Range.

Add the following to MyCollection

public string[] Slice(int start, int length)
{
  var slice = new string[length];
  Array.Copy(_collection, start, slice, 0, length);
  return slice;
}

The compiler should now show our previously broken c[1..^2] code as valid and if you make a small change to output the items from the returned slice, like this

foreach (var item in c[1..^2])
{
  Console.WriteLine(item);
}

You’ll see items from the item at index 1 through to the one 2 from the end, i.e. “Two” and “Three”.

So to wrap up “implicit Range support”, your type needs the following

  • The type is Countable i.e. has Length or Count property accessible and returning an int
  • The type contains an accessible method named Slice which takes two int params, the first being the start index the second being the length
  • The type does not have an accessible indexer which takes an Range as the first parameter

With both the implicit Index and Range code you could ofcourse write explicit code (i.e. use Index and Range in your code). Both offer helper methods to make the experience of using them consistent. Ofcourse neither are restricted to collection types and let’s look at extending Range…

Extending Range

As already mentioned, Index and Range are fairly limited in functionality, but that’s fine, they do exactly what they’re intended to do, but if you’ve ever wanted a Range of numbers in C# you’ve probably looked at Enumerable.Range, so writing something like this

foreach (var i in Enumerable.Range(1, 10))
{
  Console.WriteLine(i);
}

For fun and now we have the syntactic sugar of .. to represent a Range type it’s be cool to write something like this instead

foreach (var i in 1..10)
{
  Console.WriteLine(i);
}

Okay so we know that this is really a Range instance like this

foreach(var r in new Range(1, 10))
{
  Console.WriteLine(i);
}

but ofcourse this will not work, as Range does not support IEnumerator. No worries we’ll create an extension method, something like this

public static class RangeExtensions
{
  public static IEnumerator<int> GetEnumerator(this Range range) =>
    Enumerable.Range(range.Start.Value, range.End.Value).GetEnumerator();
}

This now allows us to use a Range within a foreach and better still we can now use the .. operator syntax

foreach (var item in 1..10)
{
  Console.WriteLine(i);
}

Note: Whilst this offers syntax along the lines of Rust – I’m not necessarily saying using Range in this way within a foreach is a great idea because Range, via Index, supports ^ (from end) syntax and we’re definitely not attempting to support such syntax in our extension method but the terse nature of it’s usage is nevertheless interesting (or for those who prefer more explicit methods then it’s probably horrible).

We could extend our fun and our extension method to add support for IEnumerable for Linq queries, whilst not as nice as the IEnumerator in it’s implicit nature, we might add to RangeExtensions, the following

public static IEnumerable<int> ToEnumerable(this Range range)
{
  foreach (var item in range)
  {
    yield return item;
  }
}

Now we can use this like with Linq, maybe like this

foreach (var i in (1..10).ToEnumerable().Where(v => v % 2 == 0))
{
  Console.WriteLine(i);
}

Which will output the even numbers between 1 and 10.

References

Ranges

Named arguments in C#

I’ve actually never had or felt a need to use named arguments in C#. Am I missing anything?

Well first off I have actually used named arguments in other languages and my immediate feeling was – this makes my code so verbose and I felt I got no real benefit from them. Certainly they can (sort of) document your code a little better, but with most/all development tools including intellisense or other tools to tell the development what parameters they were editing/adding and in some cases even show the named of the argument in the editor – hence the benefit of “documenting” seemed to be of little real use.

This all said, let’s look at what we can do with named arguments.

What are named arguments?

When we write methods/functions we pass arguments/parameters using “positional arguments”, which simply means the order of arguments must match the method signature’s argument order. For example let’s look at a simple method to add a person to some application

void AddPerson(string name, string address, int age)
{
   // do something
}

So when we use this method with positional arguments we would write

AddPerson("Scooby Doo", "Mystery Machine", 11);

In C# we also get the ability to use named arguments instead (without any changes to the method signature) by including the argument name as part of the call, so for example

AddPerson(name: "Scooby Doo", address: "Mystery Machine", age: 11);

With tools like Visual Studio 2019, this doesn’t really add anything useful (if we’re mirroring the argument positions) because Visual Studio already tells us the name of each argument in the editor. Obviously outside of Visual Studio, for example is source control, maybe this is more useful.

Surely there’s more to it than that?

Positional arguments are just that, the calling code must supply each argument in the correct position and whilst we can do the same with named arguments, you can also rearrange the arguments and hence no longer need to call using the same positions, for example let’s switch around the named arguments from earlier to give us this

AddPerson(name: "Scooby Doo", age: 11, address: "Mystery Machine");

The C# compiler will simply rearrange the arguments into their positions producing the same IL as is generated for a callee using positional arguments. Here’s an example of such code generated via dotPeek – it’s exactly the same code as for the positional arguments as one would expect.

IL_0013: ldstr        "Scooby Doo"
IL_0018: ldstr        "Mystery Machine"
IL_001d: ldc.i4.s     11 // 0x0b
IL_001f: call         void NameParamsTests.Program::AddPerson(string, string, int32)
IL_0024: nop

One area where named arguments offer some extra goodness is when we’re using optional argument, so let’s assume our AddPerson signature changes to

static void AddPerson(string name, string address = null, int age = Int32.MinValue)
{
   // do something
}

If we’re using positional arguments and we don’t have an address then we must still supply a value for the address, for example

AddPerson("Scooby Doo", null, 11);

But as we’ve seen, with named arguments the order is no longer a limiting factor, therefore we can used named arguments instead and no even bother with the address, the compiler will figure it out for us, hence we can write

AddPerson(name: "Scooby", age: 11);

Note: We can ofcourse use positional and named arguments in a method call if we wish/need to but then the named arguments would need to be in the correct position limiting the usefulness of using named arguments.

Named arguments – when we have lots of arguments

The simple AddPerson method probably isn’t a great example for using named arguments, so lets instead look at a method that takes more arguments with lots of optional arguments. If we instead have a method which looks like this

void AddPerson(
   string firstName, string lastName, int age = Int32.MinValue,
   string addressLine1 = null, string addressLine2 = null, string addressLine3 = null,
   string city = null, string county = null, string postalCode = null)
{
   // do something
}

Now we can see that if we have partial details for the person we can call this method in a more succinct manner, for example

AddPerson(age: 11, firstName: "Scooby", lastName: "Doo", postalCode: "MM1");

// or with mixed positional and named arguments

AddPerson("Scooby", "Doo", 11, postalCode: "MM1");

As you’d imagine, the compiler simply handles the setting of the optional arguments etc. as before giving us IL such as

IL_0001: ldstr        "Scooby"
IL_0006: ldstr        "Doo"
IL_000b: ldc.i4.s     11 // 0x0b
IL_000d: ldnull
IL_000e: ldnull
IL_000f: ldnull
IL_0010: ldnull
IL_0011: ldnull
IL_0012: ldstr        "MM1"
IL_0017: call         void NameParamsTests.Program::AddPerson(string, string, int32, string, string, string, string, string, string)
IL_001c: nop

Once our methods start getting more arguments and especially if lots are defaulted, then named arguments start to make sense, although with a larger number of arguments, one might question whether in fact the method call itself might be in need of refactoring, with our example here we could ofcourse create separate objects for different parts of the data and with C#’s object initializer syntax we sort of get a similar way to create “named” arguments, for example

public struct Person
{
   public string FirstName { get; set; }
   public string LastName { get; set; }
   public int Age { get; set; }
   public string Line1 { get; set; }
   public string Line2 { get; set; }
   public string Line3 { get; set; }
   public string City { get; set; }
   public string County { get; set; }
   public string PostalCode { get; set; }
}

void AddPerson(Person person)
{
   // do something
}

Now using object initializer syntax we could call this method like this

AddPerson(new Person
   {
      FirstName = "Scooby",
      LastName = "Doo",
      Age = 11,
      PostalCode = "MM1"
   });

Eureka Discovery with Steeltoe outside of ASP.NET

Whilst the previous post showed how we use Steeltoe in an ASP.NET application, sometimes we might not want to (or be able) to use all the nice methods for automatic service discovery etc.

In this post we’re going to create a simple .NET core console application and interact with the discovery service at a slightly lower level.

So…

  • Create yourself a .NET core console application
  • Add the NuGet package Steeltoe.Discovery.Eureka

We need to configure the discovery client. You can use your own configuration method but for this example we’ll hard code parameters into a EurekaClientConfig object.

var config = new EurekaClientConfig
{
   EurekaServerServiceUrls = "http://localhost:8761/eureka/",
   ShouldFetchRegistry = true,
   ShouldRegisterWithEureka = false
};

We’re just writing a client, hence we don’t want to register the application with Eureka, but we do want to fetch registry data.

Next we will create the discovery client, access the applications and get our weatherapi application…

var discoveryClient = new DiscoveryClient(config);
var applications = discoveryClient.Applications;
var service = applications?.GetRegisteredApplication("weatherapi");

Finally we want to find instances of the services associated with the application which are UP and get the URL associated with one of the instances.

var instance = service?.Instances.FirstOrDefault(info => info.Status == InstanceStatus.UP);
if(instance != null)                    
{
   var client = new HttpClient
   {
      BaseAddress = new Uri(instance.HomePageUrl)
   };
   var response = await client.GetAsync("weatherforecast");
   Console.WriteLine(await response.Content.ReadAsStringAsync());
}

If an instance is found we just simply use HttpClient to invoke a GET method on the service and output the response to the console, just to prove everything worked.

This code doesn’t use any load balancing strategies, I’ll leave that to the reader to look into as in a real world scenario we wouldn’t want all clients to use the first instance only.