What to expect in C# 8.0

C# 8.0 is the next major release version of C#. As the work is still in progress and the below list of features is not a complete list, but it will definitely give you an idea of what you will be getting from the next major release.

New Features in C# 8.0

  • Nullable Reference Types

This is one of the cool features that you will love to have in the new version of C#.

This feature will allow the developers to:

  1. Express whether a variable, parameter or result of a reference type is intended to be null or not.
  2. Provide warnings when such variables, parameters and results are not used according to that intent.

Till now, you cannot add null into ordinary reference types such as string. Now with this new feature, the developers will only get warnings, not errors.


string s = null; // Warning: Assignment of null to non-nullable reference type

But, if you really want to have null, then use a nullable reference type, such as string?


string? s = null;

A flow analysis tracks nullable reference variables and the compiler will analyze the flow of your code to see if a null value could make it to where you are using it.


void M(string? s)
{
   Console.WriteLine(s.Length); // Warning: Possible null reference exception

   if (s != null)
   {
       Console.WriteLine(s.Length); // Ok: You won't get here if s is null
   }
}

  • Recursive Patterns Matching

Pattern matching extensions for C# enable many of the benefits of algebraic data types and pattern matching from functional languages, but in a way that smoothly integrates with the feel of the underlying language.


IEnumerable GetEmployeesOnLeave()
{
    foreach (var e in Employees)
    {
      if (e is Employee { OnLeave: true, Name: string name }) yield return name;
    }
}

The pattern Employee { OnLeave: true, Name: string name }) checks that the Person is a Employee, then applies the constant pattern true to their OnLeave property to see if they’re on leave, and the pattern string name to their Name property to get their name (if non-null). Thus, if e is a Employee, is not on leave and has a non-null name, you will get the name of those employees.

  • Async Streams

Until now, C# has support for iterator methods and async methods, but no support for a method that is both an iterator and an async method. C# 8.0 is coming with this new feature by allowing for await to be used in a new form of async iterator, one that returns an IAsyncEnumerable or IAsyncEnumerator rather than an IEnumerable or IEnumerator, with IAsyncEnumerable consumable in a new await foreach


async Task GetBigResultAsync()
{
    var result = await GetResultAsync();
    if (result > 20) return result;
    else return -1;
}

What if you want to return a set or stream of results. With C# 8.0, you can achieve this


async IAsyncEnumerable GetBigResultsAsync()
{
   await foreach (var result in GetResultsAsync())
   {
      if (result > 20) yield return result;
    }
}

  • Ranges and Indices

This is another new feature of C# 8.0 which allows the developers to add a type Index, which can be used for indexing. We can create an int index that would count from the beginning or we can also add ^ operator that would count from the end.


Index i1 = 2; // number 2 from the beginning
Index i2 = ^3; // number 3 from the end

int[] a = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Console.WriteLine($"{a[i1]}, {a[i2]}"); // "2, 7"

C# 8.0 is also coming with a Range type, that consists of 2 indexes – start and end. The expression can be written as x..y


var slice = a[i1..i2]; // { 2, 3, 4, 5, 6 }

 

Dependencies: Async streams, indexers and ranges all rely on new framework types that will be part of .NET Standard 2.1. The types required to use these features won’t be available if you target C# 8.0 to .NET Framework 4.8.

 

There are some others active features in proposal and in progress state as well. We can only wait for the final version to be released to see all the features.

Advertisements

What’s New in C# 7.3

C# 7.3 was a minor release with a few enhancements to the existing features.

Features for better performance of safe code

  • Access to fixed fields without pinning.
  • Use of initializers on stackalloc arrays.
  • Use of fixed statements with any type that supports a pattern.
  • Use of additional generic constraints.
  • Reassign of ref local variables.

Some enhancements on the existing features

  • Test == and != with tuple types.
  • Attach attributes to the backing field of auto-implemented properties.
  • Method resolution when arguments differ by in has been improved.
  • Overload resolution

Let’s discuss the above in more detail

Overload Resolution

The resolution rules for overload methods have always been in question as it would pick one or more methods, though all but one could not be used, which is annoying.

With 7.3, this rule has been improved and now the compiler is able to make the obvious choice and select a method without giving compiler error. The detailed proposal is outlined below –

  1. When a method group contains both instance and static members, we discard the instance members if invoked without an instance receiver or context, and discard the static members if invoked with an instance receiver. When there is no receiver, we include only static members in a static context, otherwise both static and instance members. When the receiver is ambiguously an instance or type due to a color-color situation, we include both. A static context, where an implicit this instance receiver cannot be used, includes the body of members where no this is defined, such as static members, as well as places where this cannot be used, such as field initializers and constructor-initializers.
  2. When a method group contains some generic methods whose type arguments do not satisfy their constraints, these members are removed from the candidate set.
  3. For a method group conversion, candidate methods whose return type doesn’t match up with the delegate’s return type are removed from the set.

Tuple Comparisons

Allow expressions t1 == t2 where t1 and t2 are tuples or nullable tuple types of same cardinality, and evaluate them roughly as temp1.Item1 == temp2.Item1 && temp1.Item2 == temp2.Item2 (assuming var temp1 = t1; var temp2 = t2;).

So to compare two operands, C# 7.3 uses two points –

  • Both should be tuples
  • Both should have matching cardinality

Both operands  are evaluated in order from left to right. Each pair of elements is then used as operands to bind the operator == (or !=), recursively.

Potential breaking change in tuple comparison –

If someone wrote their own ValueTuple types with an implementation of the comparison operator, it would have previously been picked up by overload resolution. But since the new tuple case comes before overload resolution, we would handle this case with tuple comparison instead of relying on the user-defined comparison.

Auto-Implemented Property Field-Targeted Attributes

Auto-implemented properties have always been useful, but not in the case of serialization. With the new version of C#, when you are adding an attribute to auto-implemented property, just add the modifier field:

This allow developers to apply attributes directly to the backing fields of auto-implemented properties.

[Serializable]
public class Class{

    [field: NonSerialized]
    public string Property1 { get; set; }
}

Unmanaged Type constraint

The unmanaged constraint feature will give language enforcement to the class of types known as “unmanaged types”.  This new feature uses the “unmanaged” keyword to indicate the generic type must be a “type which is not a reference type and doesn’t contain reference type fields at any level of nesting.”

Unmanaged types include:

  • The primitives types such as, sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, bool
  • Any enum type
  • Pointer types
  • User defined structs

Stack Allocated Arrays

With this feature, the same syntax used to specify the values for elements in an array while initializing  can be applied to arrays that are declared with stackalloc:

int* pArr = stackalloc int[3] {1, 2, 3};
int* pArr2 = stackalloc int[] {1, 2, 3};
Span<int> arr = stackalloc [] {1, 2, 3};

The stackalloc keyword is used in an unsafe code context to allocate a block of memory on the stack.

 

Wondering what could be the new features in the next major release C# 8.0. Click here to know about the new features.

ECMAScript 2018 (ES9)

The feature set of ES9 has been set by TC39 committee. Checkout the new release process here. It is basically a 5 stage process starting with Stage 0.

Stage 0: Strawman (draft proposal after brainstorming)

Stage 1: Proposal (Make the case for the solution and identify the potential challenges)

Stage 2: Draft (Describe the syntax and semantics)

Stage 3: Candidate (Indicates that further work require users feedback)

Stage 4: Finished (The edition is ready to be included in the formal ECMAScript standard)

So, whats new in ES9 –

1. Asynchronous Iteration –

Finally!!! Its there !!!

We can use await on loops.

ES9 provides syntactic support for asynchronous iteration – synchronous iterators and asynchronous iterables, which is just like regular iterators, except that they have a next() method that returns in Promise. Have a look at the detailed proposal here


for await (const l of readLines(path)) {
console.log(l);
}

     

2. Promise.prototype.finally –

Execution of callback functions become easy with Promise. A Promise chain can either succeed or fell into a catch exception block. Sometimes, we want to run the code regardless of the output.

With ES9, we can use finally() block that allows to add the final logic at one place regardless of the outcome.

Have a look at the detailed proposal here

function doSomething()
{
method1()
.then(method2)
.catch(er => {
console.log(er);
})
.finally(() =>{
// final logic here
});
}

     

3. Regex Changes –

In total, there were 4 RegExp changes –

  • s (dotAll) flag for regular expressions –

    ES9 introduces the use of s flag which match any character, including line terminators. Have a look the the detailed proposal here


/hello.es9/s.test('hello\nes9');// true

  • RegExp named capture groups –

    Another great feature we are getting with ES9 as it improves readability and maintainability. Detailed proposal can be viewed here


const pattern = /(?\d{4})-(?\d{2})-(?\d{2})/u;
const result = pattern.exec('2018-06-25');
// → result.groups.year === '2018'
// → result.groups.month === '06'
// → result.groups.day === '25'

  • RegExp Look behind Assertions –

Assertions are regular expressions that either are true or false based on the match found. ECMAScript currently have lookahead assertions that do this in forward direction. ES9 comes with an extension to lookbehind, both positive and negative. Detailed proposal can be viewed here

Positive lookbehind make sure that the pattern is always preceded by another pattern:


const pattern = /(?<=\$)\d+/u;
const result = pattern.exec('$45');
// result[0] === '45'

Negative lookbehind make sure that the pattern is not preceded by another pattern:


const pattern = /(?<!\$)\d+/u;
const result = pattern.exec('$45');
// → result[0] === '45'

  • RegExp Unicode Property Escapes

This feature enables us to access the Unicode character properties natively in ECMAScript regular expressions as before the developers have to depend on other libraries which adds up to the run time dependency cost. Detailed proposal can be viewed here


/\p{Script=Greek}/u.test('μ') // prints true

4. Rest/Spread Properties –

The three-dot operator (…) was introduced with ECMA2015 and has been used for array literals. ES2018 introduces rest/spread feature for object destructuring as well as arrays. Detailed proposal can be viewed here


const values = {a: 5, b: 6, c: 7, d: 8};
const {a, ...n} = values;
console.log(a); // prints 5
console.log(n); // prints {b: 6, c: 7, d: 8}

 

This was all about ES9.

Let’s see what they will come up with the next version.

 

Array.map vs Array.forEach

If you are working with JavaScript, then you must have come across these two similar looking array methods: Array.prototype.map() and Array.prototype.forEach().

Most of the developers thinks that Array.map function and forEach for an Array is the same, but it is not. Lets see some examples:
1. Array.prototype.forEach
forEach can be used just like a traditional ‘for loop’ that iterates each of the array element once.

let arrayElements = ['A','C','D'];  
arrayElements.forEach((ele)=>{  
  console.log(ele);  
 })  

The above example will generate the following –
A
C
D

2. Array.prototype.map
The map() function creates a new Array with the results of calling a function for every element of the calling array.

let arrayElements = [1, 4, 6];  
var result = arrayElements .map((ele)=>{  
  return (ele * 2);  
});  
console.log(result);  

The output of the code is:
[ 2, 8, 12 ]
In the above example we are iterating through each element of Array and multiplying it by 2.

Create folders & upload images under Media in Umbraco

This is a continuation from my previous post about downloading and uploading images to media programmatically, via code.

This example code will help you create folders under Media in the following hierarchy –

Video Images

-> 2018 (current year)

-> November (current month)


public class ImageService
{
  private readonly IUmbracoContextWrapper _umbCtxtHelper;
private readonly IMediaService _mediaService;

  public ImageService(IUmbracoContextWrapper umbCtxtHelper)
  {
     _umbCtxtHelper = umbCtxtHelper;
_mediaService = _umbCtxtHelper.MediaService;
  }  

  public int UploadMedia(string imageSrc)
  {
   IMedia newImage = null;
   try
   {
     var mediaSvc = _mediaService;
     var mediaExtension = Path.GetExtension(imageSrc);
     var imageName = Guid.NewGuid() + mediaExtension;

     var image = DownloadImageFromUrl(imageSrc);

     const string rootPath = "~\\media";
     var fileName = HttpContext.Current.Server.MapPath(Path.Combine(rootPath, imageName));
     image.Save(fileName);

     // Here we are creating the folders and adding images to them
     var parentFolderId = GetFolderId();
     newImage = mediaSvc.CreateMedia(imageName, parentFolderId, "Image");

     var buffer = System.IO.File.ReadAllBytes(HttpContext.Current.Server.MapPath("~\\media\\" + imageName));

     newImage.SetValue("umbracoFile", imageName, new MemoryStream(buffer));
     mediaSvc.Save(newImage);

     if (System.IO.File.Exists(HttpContext.Current.Server.MapPath("~\\media\\" + imageName)))
     {
       System.IO.File.Delete(HttpContext.Current.Server.MapPath("~\\media\\" + imageName));
      }
   }
   catch (Exception ex)
   {
     // log the exception
   }
   return newImage.Id;
  }

  private System.Drawing.Image DownloadImageFromUrl(string imageUrl)
  {
   System.Drawing.Image image = null;
   try
   {
     var webRequest = (HttpWebRequest)WebRequest.Create(imageUrl);
     webRequest.AllowWriteStreamBuffering = true;
     webRequest.Timeout = 30000;

     var webResponse = webRequest.GetResponse();
     var stream = webResponse.GetResponseStream();
     image = System.Drawing.Image.FromStream(stream);

     webResponse.Close();
   }
   catch (Exception ex)
   {
     // log the exception
   }
   return image;
  }   

  private static int GetFolderId()
  {
    var currentYear = DateTime.Now.Year.ToString();
    var currentMonth = DateTime.Now.ToString("MMMM", CultureInfo.InvariantCulture);

    var parentFolder = GetParentFolder("Video Images")
                                  ?? CreateAndSaveMediaFolder("Video Images", -1);

    var yearFolder = GetSubFolder(parentFolder.Id, currentYear)
                                ?? CreateAndSaveMediaFolder(currentYear, genreFolder.Id);

    var monthFolder = GetSubFolder(yearFolder.Id, currentMonth)
                                 ?? CreateAndSaveMediaFolder(currentMonth, yearFolder.Id);

    return monthFolder.Id;
  }

  private static IMedia CreateAndSaveMediaFolder(string folderName, int parentFolderId)
  {
    var folder = _mediaService.CreateMedia(folderName, parentFolderId, "Folder");
    _mediaService.Save(folder);
    return folder;
  }

  private static IMedia GetSubFolder(int parentFolderId, string folderName)
  {
    var folder = _mediaService.GetChildren(parentFolderId)
                        .Where(c => c.ContentType.Name == "Folder"
                                    && c.Name.Equals(folderName))
                        .Select(f => f).FirstOrDefault();

    return folder;
  }

  private static IMedia GetParentFolder(string folderName)
  {
    var folder = _mediaService.GetRootMedia()
                         .Where(m => m.ContentType.Name == "Folder"
                                     && m.Name.Equals(folderName))
                         .Select(y => y).FirstOrDefault();

    return folder;
  }
}

public interface IUmbracoContextWrapper
{
   IMediaService MediaService { get; }
}

Upload images to Umbraco

It is easy to upload images to Media folder in Umbraco but there are some instances where you need to upload images to media folder programatically, via code.

Here is the code to do that. You can use this code to download and upload any image.


public class ImageService
{
  private readonly IUmbracoContextWrapper _umbCtxtHelper;
private readonly IMediaService _mediaService;

  public ImageService(IUmbracoContextWrapper umbCtxtHelper)
  {
     _umbCtxtHelper = umbCtxtHelper;
_mediaService = _umbCtxtHelper.MediaService;
  }  

  public int UploadMedia(string imageSrc)
  {
   IMedia newImage = null;
   try
   {
var mediaSvc = _mediaService; 
     var mediaExtension = Path.GetExtension(imageSrc);
     var imageName = Guid.NewGuid() + mediaExtension;

     var image = DownloadImageFromUrl(imageSrc);

     const string rootPath = "~\\media";
     var fileName = HttpContext.Current.Server.MapPath(Path.Combine(rootPath, imageName));
     image.Save(fileName);

     // -1 is the root folderID, i.e. Media.
     // All images will be saved under Media in Umbraco
     newImage = mediaSvc.CreateMedia(imageName, -1, "Image");
     var buffer = System.IO.File.ReadAllBytes(HttpContext.Current.Server.MapPath("~\\media\\" + imageName));

     newImage.SetValue("umbracoFile", imageName, new MemoryStream(buffer));
     mediaSvc.Save(newImage);

     if (System.IO.File.Exists(HttpContext.Current.Server.MapPath("~\\media\\" + imageName)))
     {
       System.IO.File.Delete(HttpContext.Current.Server.MapPath("~\\media\\" + imageName));
      }
   }
   catch (Exception ex)
   {
     // log the exception
   }

   return newImage.Id;
  }

  private System.Drawing.Image DownloadImageFromUrl(string imageUrl)
  {
   System.Drawing.Image image = null;
   try
   {
     var webRequest = (HttpWebRequest)WebRequest.Create(imageUrl);
     webRequest.AllowWriteStreamBuffering = true;
     webRequest.Timeout = 30000;

     var webResponse = webRequest.GetResponse();
     var stream = webResponse.GetResponseStream();
     image = System.Drawing.Image.FromStream(stream);

     webResponse.Close();
   }
   catch (Exception ex)
   {
     // log the exception
   }
   return image;
  }
}

public interface IUmbracoContextWrapper
{
   IMediaService MediaService { get; }
}

If you want to create folders under Media and upload images to those in Umbraco. Read this post here

Date Formats in SQL Server

1) SELECT CONVERT(VARCHAR,GETDATE(),100)

Result
May 13 2012 11:30AM

2) SELECT CONVERT(VARCHAR,GETDATE(),101)

Result
05/13/2012

3) SELECT CONVERT(VARCHAR,GETDATE(),102)

Result
2012.05.13

4) SELECT CONVERT(VARCHAR,GETDATE(),103)

Result
13/05/2012

5) SELECT CONVERT(VARCHAR,GETDATE(),104)

Result
13.05.2012

6) SELECT CONVERT(VARCHAR,GETDATE(),105)

Result
13-05-2012

7) SELECT CONVERT(VARCHAR,GETDATE(),106)

Result
13 May 2012

8) SELECT CONVERT(VARCHAR,GETDATE(),107)

Result
May 13, 2012

9) SELECT CONVERT(VARCHAR,GETDATE(),108)

Result
11:41:51

10) SELECT CONVERT(VARCHAR,GETDATE(),109)

Result
May 13 2012 11:43:04:267AM

11) SELECT CONVERT(VARCHAR,GETDATE(),110)

Result
05-13-2012

12) SELECT CONVERT(VARCHAR,GETDATE(),111)

Result
2012/05/13

13) SELECT CONVERT(VARCHAR,GETDATE(),112)

Result
20120513

14) SELECT CONVERT(VARCHAR,GETDATE(),113)

Result
13 May 2012 11:50:02:510

15) SELECT CONVERT(VARCHAR,GETDATE(),114)

Result
11:51:00:330

16) SELECT CONVERT(VARCHAR,GETutcDATE(),114)

Result
06:21:55:597

 

And if you are looking for a SQL query to find the SQL version, then try this

select @@version

 

download