C# - James Montemagno https://staging.montemagno.com/tag/csharp/ https://staging.montemagno.com/content/images/2017/08/MonogramIcon_Orange_NoBuffer.png C# - James Montemagno https://staging.montemagno.com/tag/csharp/ Hugo -- gohugo.io Tue, 13 Oct 2026 20:48:55 GMT 60 Enabling C# 9 in Xamarin & .NET Standard Projects https://staging.montemagno.com/enabling-c-9-in-xamarin-net-standard-projects/ 5fb7f97f36813e0039c2d3b4 Fri, 20 Nov 2020 17:34:13 GMT Whoa! .NET 5 is out and C# 9 is out! This means you are ready to use records, new pattern matching, and more! But wait a second... your apps haven't been upgraded to .NET 5 yet or are a project type that don't support .NET  so you don't have access to the new C# 9 features :( Or do you!?!?!?! Yes, of course you do! Most new features in C# are compiler based and not necessarily runtime based.  When you create a new project the compiler determines a default C# language based on these rules:

Target framework version C# language version default
.NET 5.x C# 9.0
.NET Core 3.x C# 8.0
.NET Core 2.x C# 7.3
.NET Standard 2.1 C# 8.0
.NET Standard 2.0 C# 7.3
.NET Standard 1.x C# 7.3
.NET Framework all C# 7.3

So, if you are using .NET Standard 2.0 (the default for Xamarin.Forms) you only have access to C# 7.3 by default, which is sad. However, you can override the default inside of the .csproj. Simply open it up and add the property group:

<PropertyGroup>
   <LangVersion>preview</LangVersion>
</PropertyGroup>

You can also pick the specific version of C# that you would like:

<PropertyGroup>
   <LangVersion>9.0</LangVersion>
</PropertyGroup>

Now you are ready to start using C# 9 and convert all those classes over to records... almost! I say almost because there is one quirk with enabling C# 9 in non-.NET 5 project and when you use a record you will be granted with a System.Runtime.CompilerServices.IsExternalInit is no defined or imported error.

This can easily be fixed by adding the following code into any file. I like to add it into the AssemblyInfo.cs file:

namespace System.Runtime.CompilerServices
{
    public class IsExternalInit { }
}

There you go! now you can start using all those new fancy features!! Checkout these docs:

]]>
Use C# 8 In Any .NET Project Today https://staging.montemagno.com/use-csharp-8-everywehre/ 5dc6fee984e2c7003870dfab Mon, 11 Nov 2019 18:34:00 GMT C# 8 was officially released in September at .NET Conf along side .NET Core 3 & Visual Studio 16.3 (8.3 on Mac). It is packed with tons of amazing new features that truly everyone should be using. However, there is a lot of confusing as to if you can actually use C# 8 if you aren't using .NET Core 3 or .NET Standard 2.1.

  • Short answer: YES! You can use it today.
  • Long answer: YES! You just have to turn it on and perhaps add a NuGet package or two for certain features.

When you create a new app or library there is a "default" version of C# that is used. .NET Core 3 and .NET Standard 2.1 both use 8.0, but everything else basically defaults to 7.3. If you are like me, this is an issue because I use .NET Standard 2.0, which defaults to 7.3 :(. Don't worry though because if you are building on Visual Studio 2019 16.3 (or 8.3 on Mac) it includes the C# 8 compiler, which means you can use C# 8. If it compiles it should just work.

So, just go into your csproj where you want to use C# 8 and change the LangVersion to 8.0:

<LangVersion>8.0</LangVersion>

Here is what my .NET Standard Library looks like for my Xamarin.Forms apps:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <ProduceReferenceAssembly>true</ProduceReferenceAssembly>
    <LangVersion>8.0</LangVersion>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Xamarin.Forms" Version="4.3.0.947036" />
    <PackageReference Include="Xamarin.Essentials" Version="1.3.1" />
  </ItemGroup>
</Project>

All Types Not Included

Nearly all of the C# 8 features are just syntax that can be compiled, but there are a few new types such as IAsyncEnumerable. Don't worry though as you can just install a NuGet package to get this new type similar to how we brought in ValueTuple in the past.

A Few Limitations

There are actually a few limitation to using C# 8 in non-.NET Core 3/.NET Standard 2.1 projects. A few of the features such and indexes & ranges are runtime features, which means they will not be available. That is alright though because if you try to use them, they wont compile! If you need them then you will actually need to upgrade, however there are very few limitations.

Xamarin & C# 8

One last thing that I should mention is that Xamarin apps already support all C# 8 features as of Visual Studio 16.3. This means if you turn on C# 8 in a Xamarin iOS or Android projects all of the features should be available to you. In a future update the default will be updated to 8.0 so you won't have to worry about this.

Listen

If you need more reasons to upgrade to C# 8, then listen to last week's Merge Conflict. Frank and I talked about all of our favorite features of C# 8 that you need right now.

]]>
Optimizing C# Struct Equality with IEquatable and ValueTuples https://staging.montemagno.com/optimizing-c-struct-equality-with-iequatable/ 5b746b2dcce53300bfd41229 Thu, 16 Aug 2018 19:00:42 GMT

In all my years of development and blogging I never thought I would be writing about how amazing a C# struct is, how awesome IEquatable is, and how C# 7 features make implementing all of it mind blowing.

In Xamarin.Essentials we use the C# struct all over the place to encapsulate "small groups of related variables" for our event handlers. They are groups of data that don't need to be created by the developers consuming the data and are only really used for reading the data.

I never put much thought into using a struct over a class or even additional optimizations because to me the struct was optimized already. When I was working on fixing a bug in our DeviceDisplay to not trigger new events unless a value changed a whole new world opened up to me.

Let's take the struct that we were using at the time:

public struct ScreenMetrics
{
    internal ScreenMetrics(double width, double height, double density, ScreenOrientation orientation, ScreenRotation rotation)
    {
        Width = width;
        Height = height;
        Density = density;
        Orientation = orientation;
        Rotation = rotation;
    }

    public double Width { get; set; }
    public double Height { get; set; }
    public double Density { get; set; }
    public ScreenOrientation Orientation { get; set; }
    public ScreenRotation Rotation { get; set; }
}

Mutable vs Immutable

The first issue we see here is that this struct is mutable in that you can actually change the data later on via the set properties. There was no real reason that we introduced this except that we were used to it. Since a developer should never really create one of these objects the setters should be removed and it should be marked as readonly to ensure that it is immutable, which is a pretty slick C# 7.2 feature:

public readonly struct ScreenMetrics
{
    internal ScreenMetrics(double width, double height, double density, ScreenOrientation orientation, ScreenRotation rotation)
    {
        Width = width;
        Height = height;
        Density = density;
        Orientation = orientation;
        Rotation = rotation;
    }

    public double Width { get; }
    public double Height { get; }
    public double Density { get; }
    public ScreenOrientation Orientation { get; }
    public ScreenRotation Rotation { get; }
}

Overriding Equals

Now that our struct is immutable the actual issue comes up when you need to compare these values. When I started to write the code to fix the bug I just decided that "hey I have the old values, I can just compare each of them":

 static void OnScreenMetricsChanged(ScreenMetricsChangedEventArgs e)
{
    if (currentMetrics.Width != e.Metrics.Width ||
        currentMetrics.Height != e.Metrics.Height ||
        currentMetrics.Density != e.Metrics.Density ||
        currentMetrics.Orientation != e.Metrics.Orientation ||
        currentMetrics.Rotation != e.Metrics.Rotation)
    {
        SetCurrent();
        ScreenMetricsChangedInternal?.Invoke(null, e);
    }
}

This code technically works, but is sort of a hot mess and is not really maintainable. Anyone using the library would have to write this code as well. The next logical step would be to just use .Equals on the entire metrics.

Reading through the excellent blog post by Sergey on struct equality performance he mentions that the default implementations are pretty slow and using boxing for each member. Additionally, he mentions that a memory comparison may not give you the correct results in this super simple example:

public struct MyDouble
{
    public double Value { get; }
    public MyDouble(double val) => Value = val;
}

double d1 = -0.0;
double d2 = +0.0;

// True
bool b1 = d1.Equals(d2);

//False
bool b2 = new MyDouble(d1).Equals(new MyDouble(d2));

So, this means we must override Equals!

public override bool Equals(object obj) =>
    (obj is ScreenMetrics metrics) && Equals(metrics);

public bool Equals(ScreenMetrics other) =>
    currentMetrics.Width.Equals(e.Metrics.Width) &&
    currentMetrics.Height.Equals(e.Metrics.Height) &&
    currentMetrics.Density.Equals(e.Metrics.Density) &&
    currentMetrics.Orientation.Equals(e.Metrics.Orientation) &&
    currentMetrics.Rotation.Equals(e.Metrics.Rotation);

Now we know for sure that if we call Equals, that our checks will work! However, we can do even better here with an awesome C# 7.3 feature called Tuple Equality! That is right, you can create a ValueTuple and simply compare them as they are super optimized, don't create any objects, and reduce this to a single line of code!

public bool Equals(ScreenMetrics other) =>
            (Width, Height, Density, Orientation, Rotation) == (other.Width, other.Height, other.Density, other.Orientation, other.Rotation);

Mind blown!!!

What about the HashCode

That is right! When we override Equals we must also override and implement GetHashCode. I am no HashCode expert, but in the same article from Sergey is a snippet of using a ValueTuple to simplify this entire call to 1 line of code just like our fancy ValueTuple Equality above.

public override int GetHashCode() =>
    (Height, Width, Density, Orientation, Rotation).GetHashCode();

This is really amazing code and works great for .NET Standard libraries. If you are in a .NET Core 2.1 application there is an even cooler way of doing this:

public override int GetHashCode() =>
    HashCode.Combine(Height, Width, Density, Orientation, Rotation);

I really hope this makes it to the next versions of .NET Standard as it really is discoverable.

More Optimized with IEquatable

Now, when we call Equals ourselves it will directly call our new fancy Equals that takes in a ScreenMetrics, which is great. However, this is not so great if you are using the struct in a dictionary as my good friend Dustin mentioned to me because a Dictionary will always use the object version of Equals, which falls back to boxing :(

Do not fear because if you simply implement IEquatable<T> the dictionary will use the strongly typed version! The nice thing is that we kind of actually already did this! So now we just have to do this:

public readonly struct ScreenMetrics : IEquatable<ScreenMetrics>
{
    //...
}

What about == and !=

Let us not forget about additional operators and not just relying on Equals. We can implement the == and != operators easily:

public static bool operator ==(ScreenMetrics left, ScreenMetrics right) =>
    Equals(left, right);

public static bool operator !=(ScreenMetrics left, ScreenMetrics right) =>
    !Equals(left, right);

Our Final Beautiful Struct

Here it is in all of it's glory:

public readonly struct ScreenMetrics : IEquatable<ScreenMetrics>
{
    internal ScreenMetrics(double width, double height, double density, ScreenOrientation orientation, ScreenRotation rotation)
    {
        Width = width;
        Height = height;
        Density = density;
        Orientation = orientation;
        Rotation = rotation;
    }
    public double Width { get; }
    public double Height { get; }
    public double Density { get; }
    public ScreenOrientation Orientation { get; }
    public ScreenRotation Rotation { get; }

    public static bool operator ==(ScreenMetrics left, ScreenMetrics right) =>
        Equals(left, right);

    public static bool operator !=(ScreenMetrics left, ScreenMetrics right) =>
        !Equals(left, right);

   public override bool Equals(object obj) =>
       (obj is ScreenMetrics metrics) && Equals(metrics);

    public bool Equals(ScreenMetrics other) =>
        (Width, Height, Density, Orientation, Rotation) == (other.Width, other.Height, other.Density, other.Orientation, other.Rotation);

    public override int GetHashCode() =>
        (Height, Width, Density, Orientation, Rotation).GetHashCode();
}

This also means that all of these cases work:

[Fact]
public void DeviceDisplay_Comparison_Equal()
{
    var device1 = new ScreenMetrics(
        width: 0,
        height: 0,
        density: 0,
        orientation: ScreenOrientation.Landscape,
        rotation: ScreenRotation.Rotation0);

    var device2 = new ScreenMetrics(
        width: 0,
        height: 0,
        density: 0,
        orientation: ScreenOrientation.Landscape,
        rotation: ScreenRotation.Rotation0);

    Assert.True(device1.Equals(device2));
    Assert.True(device1 == device2);
    Assert.False(device1 != device2);
    Assert.Equal(device1, device2);
    Assert.Equal(device1.GetHashCode(), device2.GetHashCode());
}

What if it was automated?

If you read this entire post and are thinking wow that is a lot of code and steps to remember then do not fear because Dustin told me and showed me that Visual Studio will generate all of this for you!!!!! Check this out:

Tune In To Merge Conflict

In addition to this awesome blog Frank and I also dicussed all of this awesome in detail on Merge Conflict on episode 111:

]]>
Paste JSON as Code with quicktype.io in Visual Studio https://staging.montemagno.com/paste-json-as-code-with-quicktype-io-in-visual-studio/ 5a78ad62da32ce0022cbd5f6 Mon, 05 Feb 2018 21:00:00 GMT

quicktype! Yes that quicktype that I blogged about late last year on how to convert JSON to C# classes in the browser. I am back talking about it again because they have made tons of great enhancements and just today released a new extension for Visual Studio 2017! I should mention here that all of this is FREE.

PasteAsCode

Watch Now, Questions Later

Want to see it in action? Checkout my short video overview:

Doesn't VS Do This?

It is true that Visual Studio has a Paste JSON as Classes feature, but it basically does the bare minimum. quicktype will automatically add in JsonProperty names, has enhanced partial classes, better names on parameters, fills in a full class and namespace, and even adds helper classes for you so you don't have to write boiler plate code.

Here is a good example of the power of quicktype. Let's take the Azure Cognitive Services Text Analytics JSON that is returned from the RESTful call.

It is pretty complex JSON with mutliple classes and arrays. If I use the "Special Paste" we do get C# classes back, but they aren't very pretty.

I now have to go through and fix all of the parameter and class names and add in JsonProperty attributes to the tops.

Now let's see the quicktype version:

Now we are talking! Look at those pretty classes and parameters!

Alright, that is enough show an tell for today. Go grab the extension and tell them Motz sent you on their community Slack!

This is NOT sponsored content. I do know the awesome quicktype team and was given early access to the extension. I just believe this is an awesome tool developers should have

]]>
C# Developers: Stop Calling .Result https://staging.montemagno.com/c-sharp-developers-stop-calling-dot-result/ 598df8f2c121b60019bf3059 Tue, 11 Jul 2017 18:15:35 GMT I love async/await Task based programming! I talk about it in all my demos, it is in all my libraries, and Frank and I did a whole Merge Conflict podcast episode on it. The problem is that I keep getting bug reports and seeing samples where it is being abused and used completely wrong. I am never a fan of calling a lot of async code in a constructor or in the OnCreate/AppDelegate, but the real issue is when I see stuff like this with .Result:

public App()
{
    try
    {
        _locator.StartListeningAsync(TimeSpan.FromSeconds(30), 100);
        var position = _locator.GetPositionAsync().Result;
        if (position != null)
        {
            App.lat = position.Latitude;
            App.lon = position.Longitude;
        }
    }
    catch (Exception c)
    {

    }

    MainPage = GetMainPage();
}

AHHHHHH!!! We aren't letting StartListeningAsync finish, and we are doing a .Result essentially locking the entire app start code! This makes me the saddest panda in the entire world.

Recently Jon Goldberger wrote a great article on getting started with async/await, but going way back 6 years ago, Stephen Toub from Microsoft 6 wrote an amazing article explaining how to use async/await when dealing with the UI and with event handlers. Both articles are great reads and yes even the 6 year old blog applies to this day.

Stephen's article boils down to this:

On your UI thread, instead of writing:

Task s = LoadStringAsync();
textBox1.Text = s.Result; // BAD ON UI

you can write:

Task s = LoadStringAsync();
textBox1.Text = await s; // GOOD ON UI

Or instead of writing:

Task t = DoWork();
t.Wait(); // BAD ON UI

you can write:

Task t = DoWork();
await t; // GOOD ON UI

Essentially calling .Result or .Wait will lock up your UI! It is true! So true that I made an entire video right here explaining why you need to stop using .Result!

]]>
My Favorite C# 7 Feature: More expression-bodied members PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); This is amazing! However, in C# 7 things get even better. Take our good old friend property …]]> https://staging.montemagno.com/my-favorite-c-7-feature-more-expression-bodied/ 598df8f2c121b60019bf2fc7 Fri, 09 Jun 2017 19:33:37 GMT I can’t help myself, I love Expression-Bodied Members from C# 6! Combined with other powerful C# features it took this code:

public void OnPropertyChanged(string name)
{
  var changed = PropertyChanged;
  if(changed == null)
    return;

  changed(this, new PropertyChangedEventArgs(name));
}

to this:

public void OnPropertyChanged(string name)=>
  PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));

This is amazing! However, in C# 7 things get even better. Take our good old friend property setters and getters:

public string Subtitle
{
  get { return subtitle; }
  set { SetProperty(ref subtitle, value); }
}

Look at all of those { and }, well no more! Here is some C# 7 for you:

public string Subtitle
{
    get => subtitle;
    set => SetProperty(ref subtitle, value);
}

You can even use our lambda friend on constructors and finalizers!!

// Expression-bodied constructor
public ExpressionMembersExample(string label) => this.Label = label;

// Expression-bodied finalizer
~ExpressionMembersExample() => Console.Error.WriteLine("Finalized!");

Mind Blown!! It is the small things that make me so happy. There are tons more great C# 7 features that you can now access in VS 2017 and VS for Mac and Frank and I discuss all of them on our podcast Merge Conflict that I hope you subscribe to!

Merge Conflict 47: You Got Some F# in My C#

]]>
Getting Started With & Learning C# https://staging.montemagno.com/getting-started-with-csharp/ 598df8f2c121b60019bf2fe4 Tue, 15 Nov 2016 17:32:43 GMT In 2006, after years of writing C++ and Java code, while attending UAT an instructor named Phil Miller introduced me to this amazing language called C# and changed my life. It was love at first “Hello World” and I have never looked back. C# is an extremely powerful, mature, and extremely cross-platform programming language that I have been using for decades. The beauty of C# of course is that you get this amazing cross-platform framework called .NET, which gives developers ability to perform RESTful service calls, perform math operations, and just about anything else you can possibly think of. With all my C# love I often forget how I learned it all and when I attempt to walk through the basics with new developers I struggle a bit. After talking with a bunch of developers over the last few months I have a 4 step plan when you want to learn C#. I am often extremely interested in how you learned C# and your recommendations, so leave them in the comments.

Learn & Write Some Code in the Browser

That is right! You would think that you would need a full IDE to even start learning and writing C#, but you would be wrong. There is a lovely and amazing website that Microsoft recently published called www.dot.net. Inside of that website is an overview of what .NET is and the languages you can use, but also an amazing learn section, where you can learn about C#, structures, functions, and TONS more…. ALL IN THE BROWSER! There is an interactive IDE/REPL thingy that will take your code and compile it in the cloud (The Azure Cloud).

Here is the direct link: https://www.microsoft.com/net/tutorials/csharp/getting-started

Grab an IDE

You have to write some code somewhere at some point and you have a lot of great options here.

Visual Studio Code

By far this is the most light weight, cross-platform, and easy to install IDE out there. Simply head to code.visualstudio.com and select Code. It works on PC, macOS, and even Linux. When you want to start writing some C# code you will also need the C# extension… the #1 extension. Simply tap on the extension section on the left and search for C#. Done!

Visual Studio Community Edition for PC

We are now in the full IDE world with Visual Studio, the best IDE ever created, and it is completely free! Community Edition is fully featured and allows you to make apps for a plethora of different platforms including mobile platforms such as iOS and Android in C# with Xamarin!

VS is a bigger install so give it some time, but you can select a console app, WPF, UWP, or Xamarin app and you are off to the races. Get it from http://www.visualstudio.com

Visual Studio for Mac

If you are over on a macOS device do not fear as Visual Studio for Machas you covered. While not as verbose as Visual Studio for PC, Visual Studio for Mac focuses on mobile iOS, Android, and macOS apps written in C# with Xamarin in addition to .NET Core, ASP.NET Core, Azure Functions, and even Unity development. This is also completely FREE and easy to install by heading to visualstudio.com.

On the Go with Continuous for iPad

My good friend Frank Krueger is an absolute genius and created his own fully featured C# IDE for the iPad called Continuous. It is the only paid IDE coming in at $9.99, but it is amazing and you can even write full iOS apps in C# with Xamarin with it.

Check out more at http://continuous.codes

Take Bob Tabor’s MVA Class

One of the biggest recommendations that I have heard is the now extremely famous and completely free C# class by Bob Tabor. This free class on Microsoft Virtual Academy has literally changed my friends careers by teaching them C#. Bob is extremely well known and has great classes on a bunch of awesome languages, but his C# is top rated, so check them out right now on Microsoft Virtual Academy.

Pick a Platform & Go

Once you have C# basics down it is time to go pick a platform to start tackling. Write a simple application for web, mobile, or desktop that does one or two things on a single page. With the C# basics down you are able to go off and learn some platform specifics. Here is a good place to start:

Have Fun

C# is my favorite programming language in the entire world and I hope that it soon becomes your favorite too.

]]>
Fun with Windows 8 DataItemTemplates https://staging.montemagno.com/fun-with-windows-8-dataitemtemplates/ 598df8f2c121b60019bf3058 Sat, 15 Dec 2012 03:34:00 GMT So you are probably using GridViews and ListViews all over the place. In some instances you will most likely even have a situation where you you have a DataSource with a few DataGroups. Each DataGroup might actually be all different or it might even have different items in its list. If you have a nice base class such as StandardDataItem then this will work just fine. So here is where the fun comes in because usually each DataItem is going to have a different DataTemplate.

This is where DataItemTemplates come in.

So first we will pretender I have a few items such as:

  1. MovieItem
  2. RecordedTVItem

I want to show the latest 5 or 6 from each category on my home screen of my app.

So the first thing you will want to do is construct up a DataSource:

var group1 = new StandardDataGroup("recent_movies", "Recent Movies", "Recent Movies", string.Empty, string.Empty, 0, movies);

var group2 = new StandardDataGroup("recent_recordings", "Recent Recordings", "Recent Recordings", string.Empty, string.Empty, 0, recordings);

DataSource.AllGroups.Add(group1);
DataSource.AllGroups.Add(group2);

If you don’t have/know about StandardDataGroup you can start up any new Window Store App sample and find them. They are a good basis for you to start.

Alright next up I am going to assume that you already created ItemTemplates for each. We will assume

  1. MovieItemTemplate
  2. RecordedTVItemTemplate

So now we will create a new class called “MainItemTemplateSelector.cs”

Now the key here is to derive from “DataTemplateSelector”

public class MainItemTemplateSelector : DataTemplateSelector
{
}

All you have to do is override 1 method here:

protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
{
    var movie = item as MovieDataItem;

    if (movie != null)
    {
        return Application.Current.Resources["MovieItemTemplate"] as DataTemplate;
    }

    var recorded = item as RecordedTVDataItem;

    if (recorded != null)
    {
        return Application.Current.Resources["RecordedTVItemTemplate"] as DataTemplate;
    }

    return null; //probably throw exception as this would be bad
}

Alright and now for the fun stuff in your XAML

First in the .Resources you will want to specify:

 common:MainItemTemplateSelector x:Key="MainItemTemplateSelector"

Then you will want to specify the ItemTemplateSelector in your grid view or itemsview:

<GridView ItemsSource="{Binding Source={StaticResource groupedItemsViewSource}}" ItemTemplateSelector="{StaticResource MainItemTemplateSelector}"

Boom you are good to go!

Now you will want to do some custom work on the back end when you click one of these. you will have to do something similar as well for the item that is selected so you can navigate to the correct page.

]]>