Skip to content

Instantly share code, notes, and snippets.

@RajaniCode
Last active February 7, 2025 01:30
Show Gist options
  • Save RajaniCode/1d9912aaf183567ed082aa72f0dec9ea to your computer and use it in GitHub Desktop.
Save RajaniCode/1d9912aaf183567ed082aa72f0dec9ea to your computer and use it in GitHub Desktop.
CS13.cs
// CS 13
/*
$ wget https://builds.dotnet.microsoft.com/dotnet/Sdk/9.0.102/dotnet-sdk-9.0.102-linux-x64.tar.gz
$ DOTNET_FILE=dotnet-sdk-9.0.102-linux-x64.tar.gz
$ export DOTNET_ROOT=$HOME/.dotnet
$ mkdir -p "$DOTNET_ROOT" && tar zxf "$DOTNET_FILE" -C "$DOTNET_ROOT"
$ export PATH=$PATH:$DOTNET_ROOT:$DOTNET_ROOT/tools
$ vim ~/.bashrc
export DOTNET_ROOT=$HOME/.dotnet
export PATH=$PATH:$DOTNET_ROOT:$DOTNET_ROOT/tools
*/
/*
1. params collections
2. New lock object
3. New escape sequence
4. Method group natural type
5. Implicit index access
6. ref and unsafe in iterators and async methods
7. allows ref struct
8. ref struct interfaces
9. More partial members
10. Overload resolution priority
*/
/*************************************************************************************************************************/
// Explicit using directives
/*************************************************************************************************************************/
using System.Text.RegularExpressions;
/*************************************************************************************************************************/
/*************************************************************************************************************************/
Console.WriteLine("Environment Properties");
/*************************************************************************************************************************/
EnvironmentProperties propertiesEnvironment = new();
propertiesEnvironment.Print();
Console.WriteLine();
/*************************************************************************************************************************/
/*************************************************************************************************************************/
Console.WriteLine("1. params collections");
/*************************************************************************************************************************/
Greek gre = new();
Console.WriteLine("Overload Resolution: Array");
gre.WriteOverloadParamsCollections(new string[] { "Zeta", "Eta", "Theta", "Iota", "Kappa "});
Console.WriteLine("Overload Resolution: Anonymous Array");
gre.WriteOverloadParamsCollections(new [] { "Lambda", "Mu", "Nu", "Xi", "Omicron" });
Console.WriteLine("Most Efficient Overload Resolution : ReadOnlySpan");
gre.WriteOverloadParamsCollections("Phi", "Chi", "Psi", "Omega");
var names = new List<Greek>
{
new Greek("Lambda", "Mu"),
new Greek("Nu", "Xi"),
new Greek("Omicron", "Pi"),
new Greek("Rho", "Sigma"),
new Greek("Tau", "Upsilon")
};
Console.WriteLine("Overload Resolution: IEnumerable");
gre.WriteOverloadParamsCollections(names.Select(x => x.Moniker));
Console.WriteLine("Overload Resolution: Linq");
gre.WriteOverloadParamsCollections(from x in names select x.Sobriquet);
Console.WriteLine();
/*************************************************************************************************************************/
/*************************************************************************************************************************/
Console.WriteLine("2. lock object");
/*************************************************************************************************************************/
ObjectLockType typeObjectLock = new();
typeObjectLock.ObjectLockMethod();
ThreadingLockType typeThreadingLock = new();
typeThreadingLock.ThreadingLockMethod();
Console.WriteLine();
/*************************************************************************************************************************/
/*************************************************************************************************************************/
Console.WriteLine("3. Escape sequence \\e");
/*************************************************************************************************************************/
// CS 13 introduces a new escape sequence for the character you know as ESCAPE or ESC.
// You previously had to type this as a variation of \u001b. This new sequence is especially convenient when interacting with terminals with the VT100/ANSI escape codes to System.Console.
// Pre-CS 13
Console.WriteLine("\u001b[1mThis is a bold text\u001b[0m");
// CS 13
// You can use \e as a character literal escape sequence for the ESCAPE character,Unicode U+001B.
// Previously, you used \u001b or \x1b.
// Using \x1b wasn't recommended because if the next characters following 1b were valid hexadecimal digits, those characters became part of the escape sequence.
Console.WriteLine("\e[1mThis is a bold text\e[0m");
Console.WriteLine();
/*************************************************************************************************************************/
/*************************************************************************************************************************/
Console.WriteLine("4. Method group natural type improvements");
/*************************************************************************************************************************/
var f = GetTodo; // the type of f is Func<ToDo>
// 4. Method group natural type
// This feature makes small optimizations to overload resolution involving method groups.
// A method groups is a method and all overloads with the same name.
// The previous behavior was for the compiler to construct the full set of candidate methods for a method group.
// If a natural type was needed, the natural type was determined from the full set of candidate methods.
// The new behavior is to prune the set of candidate methods at each scope, removing those candidate methods that aren't applicable.
// Typically, the removed methods are generic methods with the wrong arity, or constraints that aren't satisfied.
// The process continues to the next outer scope only if no candidate methods are found.
// This process more closely follows the general algorithm for overload resolution.
// If all candidate methods found at a given scope don't match, the method group doesn't have a natural type.
// Method group natural type improvements
// The natural type of an expression is the type determined by the compiler, such as when the type is assigned to var or Delegate.
// That’s straightforward when it’s a simple type. In CS 10 we added support for method groups.
// Method groups are used when you include the name of a method without parentheses as a delegate.
Todo GetTodo() => new(Id: 0, Name: "Name");
GetTodo().Print();
// CS 13 refines the rules for determining the natural type to consider candidates by scope and to prune candidates that have no chance of succeeding. Updating these rules will mean less compiler errors when working with method groups.
Console.WriteLine();
/*************************************************************************************************************************/
/*************************************************************************************************************************/
Console.WriteLine("5. Implicit index access");
/*************************************************************************************************************************/
// The implicit "from the end" index operator, ^, is now allowed in an object initializer expression.
// For example, you can now initialize an array in an object initializer.
var range = new Numbers
{
Values =
{
[1] = 111,
[^1] = 444 // Works starting in CS 13
}
// x.Values[1] is 111
// x.Values[4] is 444 since it is the last element
};
Console.WriteLine($"Index from the end in initializers: {string.Join(", ", range.Values)}");
// For e.g., you can create an array that counts down from 9 to 0.
// In versions before CS 13, the ^ operator can't be used in an object initializer.
// You need to index the elements from the front.
var countdown = new TimerRemaining()
{
Buffer =
{
[^1] = 0,
[^2] = 1,
[^3] = 2,
[^4] = 3,
[^5] = 4,
[^6] = 5,
[^7] = 6,
[^8] = 7,
[^9] = 8,
[^10] = 9
}
};
Console.WriteLine($"Index from the end in initializers: {string.Join(", ", countdown.Buffer)}");
Console.WriteLine();
/*************************************************************************************************************************/
/*************************************************************************************************************************/
Console.WriteLine("6. ref and unsafe in iterators and async methods");
/*************************************************************************************************************************/
RefAndUnsafeInIteratorsAndAsyncMethods iteratorsAndAsyncMethodsRefAndUnsafe = new();
string?[] namesArray = [ "Alpha", "Beta", "Gamma", string.Empty, "", "Delta", "", string.Empty, "Epsilon", null, null, "Beta", null, "", string.Empty, "Zeta", "Eta", "Zeta" ]; // Length: 18
IAsyncEnumerator<string?> asyncEnumeratorNames = iteratorsAndAsyncMethodsRefAndUnsafe.GetAsyncEnumerator<string?>(namesArray);
await iteratorsAndAsyncMethodsRefAndUnsafe.PrintAsyncEnumerator<string?>(asyncEnumeratorNames, namesArray.Length);
int?[] numbersArray = [ 1, 2, 3, 4, 5, null, null, 2, null, 6, 7, 6 ]; // Length: 12
IAsyncEnumerator<int?> asyncEnumeratorNumbers = iteratorsAndAsyncMethodsRefAndUnsafe.GetAsyncEnumerator<int?>(numbersArray);
await iteratorsAndAsyncMethodsRefAndUnsafe.PrintAsyncEnumerator<int?>(asyncEnumeratorNumbers, numbersArray.Length);
UnsafeType[] unsafeTypeArray = new UnsafeType[26];
Enumerable.Range(0, 26).ToList().ForEach(
x =>
{
char c = (char)((x + 65));
unsafeTypeArray[x] = iteratorsAndAsyncMethodsRefAndUnsafe.GetEmbeddedArray(c);
}
);
IAsyncEnumerator<UnsafeType> asyncEnumeratorUnsafeTypes = iteratorsAndAsyncMethodsRefAndUnsafe.GetAsyncEnumerator<UnsafeType>(unsafeTypeArray);
await iteratorsAndAsyncMethodsRefAndUnsafe.PrintAsyncEnumeratorUnsafeType(asyncEnumeratorUnsafeTypes, unsafeTypeArray.Length);
IAsyncEnumerator<UnsafeType> asyncEnumeratorUnsafeTypesVerifyYieldReturnNotInUnsafeBlock =
iteratorsAndAsyncMethodsRefAndUnsafe.GetAsyncEnumeratorUnsafeType(unsafeTypeArray);
await iteratorsAndAsyncMethodsRefAndUnsafe.PrintAsyncEnumeratorUnsafeType(asyncEnumeratorUnsafeTypesVerifyYieldReturnNotInUnsafeBlock, unsafeTypeArray.Length);
Console.WriteLine();
/*************************************************************************************************************************/
/*************************************************************************************************************************/
Console.WriteLine("7. allows ref struct");
/*************************************************************************************************************************/
// Prior to CS 13, ref struct types couldn't be declared as the type argument for a generic type or method.
// Now, generic type declarations can add an anti-constraint, allows ref struct.
// This anti-constraint declares that the type argument supplied for that type parameter can be a ref struct type.
// The compiler enforces ref safety rules on all instances of that type parameter.
// This enables types such as System.Span<T> and System.ReadOnlySpan<T> to be used with generic algorithms, where applicable. Y
// CS 13 adds a new way to specify capabilities for generic type parameters.
// By default, type parameters cannot be ref struct.
// CS 13 lets you specify that a type parameter can be a ref struct, and applies the appropriate rules.
// While other generic constraints limit the set of types that can be used as the type parameter, this new specification expands the allowed types.
// We think of this as an anti-constraint since it removes rather than adds a restriction.
// The syntax allows ref struct in the where clause, where allows indicates this expansion in usage.
T Identity<T>(T p) where T : allows ref struct => p;
int[] randoms = new int[10];
Enumerable.Range(0, 10).ToList().ForEach(
x =>
{
// randoms[x] = new Random().Next(0, 11);
randoms[x] = Random.Shared.Next(0, 11);
}
);
Span<int> localSpan = Identity(new Span<int>(new int[10]));
Console.WriteLine($"Span<int>: {string.Join(", ", localSpan.ToArray())}");
localSpan = Identity(new Span<int>(randoms));
Console.WriteLine($"Span<int>: {string.Join(", ", localSpan.ToArray())}");
Console.WriteLine();
/*************************************************************************************************************************/
/*************************************************************************************************************************/
Console.WriteLine("8. ref struct interfaces");
/*************************************************************************************************************************/
// ref struct types can't be converted to an interface type including via a reference conversion, boxing conversion, unboxing conversion, wrapping conversion, or null type conversion
// IForRefStructures iForRefStruc = new RefStructure();
// IForRefStructures iForRefStruc = new ReadonlyRefStructure() as IForRefStructures;
Console.WriteLine(IForRefStructures.StaticField);
RefStructure refStruct = new RefStructure();
refStruct.Print();
ReadonlyRefStructure readonlyRefStruct = new ReadonlyRefStructure();
readonlyRefStruct.Print();
Console.WriteLine();
/*************************************************************************************************************************/
/*************************************************************************************************************************/
Console.WriteLine("9. Partial properties");
/*************************************************************************************************************************/
PartialProperties propertiesPartial = new();
propertiesPartial.Print();
Console.WriteLine();
/*************************************************************************************************************************/
/*************************************************************************************************************************/
Console.WriteLine("10. Overload resolution priority");
/*************************************************************************************************************************/
OverloadResolutionPriority priorityOverloadResolution = new();
priorityOverloadResolution.Method(1);
/*************************************************************************************************************************/
/*************************************************************************************************************************/
// 1. params collections
/*************************************************************************************************************************/
class Greek
{
public Greek() { }
public Greek(string? moniker, string? sobriquet)
{
Moniker = moniker;
Sobriquet = sobriquet;
}
public string? Moniker { get; set; }
public string? Sobriquet { get; set; }
public void WriteOverloadParamsCollections(params string[] names) => Console.WriteLine($"params string[] names: {string.Join(", ", names)}");
// The params modifier isn't limited to array types.
// You can now use params with any recognized collection type, including System.Span<T>, System.ReadOnlySpan<T>, and types that implement System.Collections.Generic.IEnumerable<T> and have an Add method. In addition to concrete types, the interfaces System.Collections.Generic.IEnumerable<T>, System.Collections.Generic.IReadOnlyCollection<T>, System.Collections.Generic.IReadOnlyList<T>, System.Collections.Generic.ICollection<T>, and System.Collections.Generic.IList<T> can also be used.
// When an interface type is used, the compiler synthesizes the storage for the arguments supplied.
// You can learn more in the feature specification for params collections.
// NB
// WriteOverloadParamsCollections("Phi", "Chi", "Psi", "Omega");
// The call is ambiguous between the following methods or properties: 'Greek.WriteOverloadParamsCollections(params List<string?>)' and 'Greek.WriteOverloadParamsCollections(params ReadOnlySpan<string?>)'
// 10. Overload resolution priority
[System.Runtime.CompilerServices.OverloadResolutionPriority(1)]
public void WriteOverloadParamsCollections(params List<string?> names) => Console.WriteLine($"params List<string?> names: {string.Join(", ", names)}");
// Whenever you call a method that has a parameter that is an IEnumerable<T>, you can pass the results of a LINQ expression.
// If the IEnumerable<T> parameter has the params modifier, you can also pass a comma delimited list.
// You can use a comma delimited list when you have constants and a LINQ expression when you need it.
public void WriteOverloadParamsCollections(params ReadOnlySpan<string?> names) => Console.WriteLine($"params ReadOnlySpan<string?> names: {string.Join(", ", names)}");
public void WriteOverloadParamsCollections(params IEnumerable<string?> names) => Console.WriteLine($"params IEnumerable<string?> names: {string.Join(", ", names)}");
}
/*************************************************************************************************************************/
/*************************************************************************************************************************/
// 2. lock object
/*************************************************************************************************************************/
// The .NET 9 runtime includes a new type for thread synchronization, the System.Threading.Lock type.
// This type provides better thread synchronization through its API.
// The Lock.EnterScope() method enters an exclusive scope.
// The ref struct returned from that supports the Dispose() pattern to exit the exclusive scope.
// CS 11 .NET 9 includes a new System.Threading.Lock type for mutual exclusion that can be more efficient than locking on an arbitrary System.Object instance.
// The System.Threading.Lock type proposal has more about this type and why it was created. Over time, this type is expected to become the primary mechanism used for most locking in CS code.
class ObjectLockType
{
private object objectLock = new object();
public void ObjectLockMethod()
{
lock (objectLock)
{
Console.WriteLine($"Type: {objectLock.GetType()}");
}
}
}
class ThreadingLockType
{
// The CS lock statement recognizes if the target of the lock is a Lock object.
// If so, it usesthe updated API, rather than the traditional API using System.Threading.Monitor.
// The compiler also recognizes if you convert a Lock object to another type and the Monitor based code would be generated.
// The following line is the only change
// private System.Threading.Lock threadingLock = new System.Threading.Lock();
private Lock threadingLock = new();
public void ThreadingLockMethod()
{
lock (threadingLock)
{
Console.WriteLine($"Type: {threadingLock.GetType()}");
}
}
}
/*************************************************************************************************************************/
/*************************************************************************************************************************/
// 4. Method group natural type improvements
/*************************************************************************************************************************/
class Todo(int Id, String Name)
{
public void Print() => Console.WriteLine($"Id: {Id}, Name: {Name}");
}
/*************************************************************************************************************************/
/*************************************************************************************************************************/
// 5. Implicit index access
/*************************************************************************************************************************/
class Numbers
{
public int[] Values { get; set; } = new int[5];
}
class TimerRemaining
{
public int[] Buffer { get; set; } = new int[10];
}
/*************************************************************************************************************************/
/*************************************************************************************************************************/
// 6. ref and unsafe in iterators and async methods
/*************************************************************************************************************************/
ref struct RefStructType { }
// <AllowUnsafeBlocks>true</AllowUnsafeBlocks> in .csproj
unsafe struct UnsafeStructure
{
public fixed char fixedBuffer[128];
}
// <AllowUnsafeBlocks>true</AllowUnsafeBlocks> in .csproj
unsafe class UnsafeType
{
public UnsafeStructure buffer = default;
}
class RefAndUnsafeInIteratorsAndAsyncMethods
{
public UnsafeType GetEmbeddedArray(char character)
{
UnsafeType typeUnsafe = new();
// <AllowUnsafeBlocks>true</AllowUnsafeBlocks> in .csproj
unsafe
{
// Pin the buffer to a fixed location in memory.
fixed (char* charPtr = typeUnsafe.buffer.fixedBuffer)
{
*charPtr = character;
}
// Access safely through the index:
// char c = typeUnsafe.buffer.fixedBuffer[0];
// Console.WriteLine(c);
// Modify through the index:
typeUnsafe.buffer.fixedBuffer[0] = character;
// Console.WriteLine(typeUnsafe.buffer.fixedBuffer[0]);
}
return typeUnsafe;
}
// A type parameter specified with allows ref struct has all of the behaviors and restrictions of a ref struct type.
// Before CS 13, iterator methods (methods that use yield return) and async methods couldn't declare local ref variables, nor could they have an unsafe context.
// In CS 13, async methods can declare ref local variables, or local variables of a ref struct type.
// However, those variables can't be accessed across an await boundary.Neither can they be accessed across a yield return boundary.
// This relaxed restriction enables the compiler to allow verifiably safe use of ref local variables and ref struct types in more places.
// You can safely use types like System.ReadOnlySpan<T> in these methods.
// The compiler tells you if you violate safety rules.
// In the same fashion, CS 13 allows unsafe contexts in iterator methods.
// However, all yield return and yield break statements must be in safe contexts.
public async IAsyncEnumerator<T> GetAsyncEnumerator<T>(T[] paramArray)
{
T[] array = paramArray;
ref T[] refLocalArray = ref array;
// In CS 13, async methods can declare ref local variables, or local variables of a ref struct type.
/*
RefStructType typeRefStructType = new();
ref RefStructType refLocalRefStructType = ref typeRefStructType;
*/
IEnumerator<T> enumerator = refLocalArray.ToList<T>().GetEnumerator();
while (enumerator.MoveNext())
{
await Task.Delay(10);
T enumeratorCurrent = enumerator.Current;
yield return enumeratorCurrent;
}
}
public async IAsyncEnumerator<UnsafeType> GetAsyncEnumeratorUnsafeType(UnsafeType[] paramArray)
{
UnsafeType[] array = paramArray;
ref UnsafeType[] refLocalArray = ref array;
IEnumerator<UnsafeType> enumerator = refLocalArray.ToList<UnsafeType>().GetEnumerator();
while (enumerator.MoveNext())
{
await Task.Delay(10);
UnsafeType enumeratorCurrent = enumerator.Current;
unsafe
{
char c = enumeratorCurrent.buffer.fixedBuffer[0];
// Console.WriteLine($"{c}");
}
// Cannot use 'yield return' in an 'unsafe' block
yield return enumeratorCurrent;
}
}
public async Task PrintAsyncEnumerator<T>(IAsyncEnumerator<T> asyncEnumerator, int arrayLength)
{
int asyncEnumeratorListCounter = 0;
while (await asyncEnumerator.MoveNextAsync())
{
asyncEnumeratorListCounter++;
T asyncEnumeratorCurrent = asyncEnumerator.Current;
if (asyncEnumeratorListCounter < arrayLength)
{
Console.Write($"{asyncEnumeratorCurrent}, ");
}
else
{
Console.Write($"{asyncEnumeratorCurrent}");
}
}
Console.WriteLine();
}
public async Task PrintAsyncEnumeratorUnsafeType(IAsyncEnumerator<UnsafeType> asyncEnumerator, int arrayLength)
{
int asyncEnumeratorListCounter = 0;
while (await asyncEnumerator.MoveNextAsync())
{
asyncEnumeratorListCounter++;
UnsafeType asyncEnumeratorCurrent = asyncEnumerator.Current;
unsafe
{
if (asyncEnumeratorListCounter < arrayLength)
{
// Access safely through the index:
char c = asyncEnumeratorCurrent.buffer.fixedBuffer[0];
Console.Write($"{c}, ");
}
else
{
// Access safely through the index:
char c = asyncEnumeratorCurrent.buffer.fixedBuffer[0];
Console.Write($"{c}");
}
}
}
Console.WriteLine();
}
}
/*************************************************************************************************************************/
/*************************************************************************************************************************/
// 8. ref struct interfaces
/*************************************************************************************************************************/
// Prior to CS 13, ref struct types weren't allowed to implement interfaces.
// Beginning with CS 13, they can.
// To ensure ref safety rules, a ref struct type can't be converted to an interface type.
// That is a boxing conversion, and could violate ref safety.
interface IForRefStructures
{
// interface static constructor
static IForRefStructures() {}
// interface static field
static string StaticField = "Cannot implement interface default/virtual default instance method for ref struct or readonly ref struct";
// interface static abstract method
static abstract void StaticAbstractMethod();
// interface instance abstract method
abstract void InstanceAbstractMethod();
// interface static virtual method
static virtual void StaticVirtualMethod() => Console.WriteLine("interface methods must declare body (or default implementation) unless it is not marked abstract, extern, or partial");
// Cannot implement interface default/virtual default instance method for ref struct or readonly ref struct
// interface instance virtual method
// virtual void InstanceVirtualMethod() => Console.WriteLine("interface methods must declare body (or default implementation) unless it is not marked abstract, extern, or partial");
// interface static default method
static void StaticDefaaultMethod() => Console.WriteLine("interface methods must declare body (or default implementation) unless it is not marked abstract, extern, or partial");
// interface instance method
void Print();
// Cannot implement interface default/virtual default instance method for ref struct or readonly ref struct
// void InstanceDefaultMethod() => Console.WriteLine("interface default instance method");
}
ref struct RefStructure : IForRefStructures
{
public static void StaticAbstractMethod() { }
public void InstanceAbstractMethod() { }
public void Print()
{
Console.WriteLine("Prior to CS 13, ref struct types weren't allowed to implement interfaces.");
}
}
readonly ref struct ReadonlyRefStructure : IForRefStructures
{
public static void StaticAbstractMethod() { }
public void InstanceAbstractMethod() { }
public void Print()
{
Console.WriteLine(@$"""Beginning with CS 13, ref struct types including readonly ref struct types can implement interfaces.
To ensure ref safety rules, a ref struct type can't be converted to an interface type.
That is a boxing conversion, and could violate ref safety.""".Trim('"'));
}
}
/*************************************************************************************************************************/
/*************************************************************************************************************************/
// 9. Partial properties
/*************************************************************************************************************************/
// You can declare partial properties and partial indexers in CS 13.
// Partial properties and indexers generally follow the same rules as partial methods.
// You create one declaring declaration and one implementing declaration.
// The signatures of the two declarations must match.
// One restriction is that you can't use an auto-property declaration for a partial property.
// Properties that don't declare a body are considered the declaring declaration.
// You can learn more in the article on partial members.
// Like partial methods their primary purpose is to support source generators.
// Partial methods have been available for many releases with additional improvements in CS 9.
// Partial properties are much like their partial method counterparts.
// For example, starting with .NET 7 (CS 12), the regular expression source generator creates efficient code for methods.
partial class PartialProperties
{
[GeneratedRegex("abc|def")]
private partial Regex AbcOrDefMethod();
// In .NET 9 (CS 13), the Regex source generator has been updated and if you prefer to use a property, you can also use:
[GeneratedRegex("abc|def")]
private partial Regex AbcOrDefProperty { get; }
// Partial properties will make it easier for source generator designers to create natural feeling APIs.
public void Print()
{
Console.WriteLine($"Pre-CS 13 Regex Method IsMatch(\"abc\"): {AbcOrDefMethod().IsMatch("abc")}");
Console.WriteLine($"Pre-CS 13 Regex Method IsMatch(\"def\"): {AbcOrDefMethod().IsMatch("def")}");
Console.WriteLine($"Pre-CS 13 Regex Method IsMatch(\"xyz\"): {AbcOrDefMethod().IsMatch("xyz")}");
Console.WriteLine($"CS 13 Regex Property IsMatch(\"abc\"): {AbcOrDefProperty.IsMatch("abc")}");
Console.WriteLine($"CS 13 Regex Property IsMatch(\"def\"): {AbcOrDefProperty.IsMatch("def")}");
Console.WriteLine($"CS 13 Regex Property IsMatch(\"xyz\"): {AbcOrDefProperty.IsMatch("xyz")}");
}
}
/*************************************************************************************************************************/
/*************************************************************************************************************************/
// 10. Overload resolution priority
/*************************************************************************************************************************/
class OverloadResolutionPriority
{
[System.Runtime.CompilerServices.OverloadResolutionPriority(1)]
public void Method(ulong n) => Console.WriteLine("ulong called.");
[System.Runtime.CompilerServices.OverloadResolutionPriority(2)]
public void Method(long n) => Console.WriteLine("long called.");
[System.Runtime.CompilerServices.OverloadResolutionPriority(3)]
public void Method(uint n) => Console.WriteLine("uint called.");
[System.Runtime.CompilerServices.OverloadResolutionPriority(4)]
public void Method(int n) => Console.WriteLine("int called.");
[System.Runtime.CompilerServices.OverloadResolutionPriority(5)]
public void Method(ushort n) => Console.WriteLine("ushort called.");
[System.Runtime.CompilerServices.OverloadResolutionPriority(6)]
public void Method(short n) => Console.WriteLine("short called.");
[System.Runtime.CompilerServices.OverloadResolutionPriority(7)]
public void Method(byte n) => Console.WriteLine("byte called.");
[System.Runtime.CompilerServices.OverloadResolutionPriority(8)]
public void Method(sbyte n) => Console.WriteLine("sbyte called.");
}
/*************************************************************************************************************************/
/*************************************************************************************************************************/
// Environment Properties
/*************************************************************************************************************************/
class EnvironmentProperties
{
public void Print()
{
System.Console.WriteLine($"System.Environment.OSVersion: {System.Environment.OSVersion}");
System.Console.WriteLine($"System.Environment.OSVersion.Platform: {System.Environment.OSVersion.Platform}");
System.Console.WriteLine($"System.Environment.OSVersion.Version: {System.Environment.OSVersion.Version}");
System.Console.WriteLine($"System.Environment.OSVersion.VersionString: {System.Environment.OSVersion.VersionString}");
System.Console.WriteLine($"System.Environment.OSVersion.Version.Major: {System.Environment.OSVersion.Version.Major}");
System.Console.WriteLine($"System.Environment.OSVersion.Version.Minor: {System.Environment.OSVersion.Version.Minor}");
System.Console.WriteLine($"System.Environment.OSVersion.Platform == System.PlatformID.Win32NT: {System.Environment.OSVersion.Platform == System.PlatformID.Win32NT}");
System.Console.WriteLine($"System.Environment.OSVersion.Platform == System.PlatformID.Unix: {System.Environment.OSVersion.Platform == System.PlatformID.Unix}");
// Mono JIT compiler version 6.12.0.206 'PlatformID' does not contain a definition for 'Other'
// System.Console.WriteLine($"System.Environment.OSVersion.Platform == System.PlatformID.Other: {System.Environment.OSVersion.Platform == System.PlatformID.Other}");
// System.PlatformID.Win32NT
// System.Console.WriteLine($"System.Environment.OSVersion.ServicePack: {System.Environment.OSVersion.ServicePack}");
// System.Environment.Version property returns the .NET runtime version for .NET 5+ and .NET Core 3.x
// Not recommend for .NET Framework 4.5+
System.Console.WriteLine($"System.Environment.Version: {System.Environment.Version}");
// <-- Keep this information secure! -->
// System.Console.WriteLine($"System.Environment.UserName: {System.Environment.UserName}");
// <-- Keep this information secure! -->
// System.Console.WriteLine($"System.Environment.MachineName: {System.Environment.MachineName}");
// <-- Keep this information secure! -->
// System.Console.WriteLine($"System.Environment.UserDomainName: {System.Environment.UserDomainName}");
System.Console.WriteLine($"System.Environment.Is64BitOperatingSystem: {System.Environment.Is64BitOperatingSystem}");
System.Console.WriteLine($"System.Environment.Is64BitProcess: {System.Environment.Is64BitProcess}");
// <-- Keep this information secure! -->
// System.Console.WriteLine("CurrentDirectory: {0}", System.Environment.CurrentDirectory);
// <-- Keep this information secure! -->
// System.Console.WriteLine("SystemDirectory: {0}", System.Environment.SystemDirectory);
// RuntimeInformation.FrameworkDescription property gets the name of the .NET installation on which an app is running
// .NET 5+ and .NET Core 3.x // .NET Framework 4.7.1+ // Mono 5.10.1+
System.Console.WriteLine($"System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription: {System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription}");
System.Console.WriteLine($"System.Runtime.InteropServices.RuntimeInformation.ProcessArchitecture: {System.Runtime.InteropServices.RuntimeInformation.ProcessArchitecture}");
System.Console.WriteLine($"System.Runtime.InteropServices.RuntimeInformation.OSArchitecture: {System.Runtime.InteropServices.RuntimeInformation.OSArchitecture}");
System.Console.WriteLine($"System.Runtime.InteropServices.RuntimeInformation.OSDescription): {System.Runtime.InteropServices.RuntimeInformation.OSDescription}");
// Mono JIT compiler version 6.12.0.206 'RuntimeInformation' does not contain a definition for 'RuntimeIdentifier'
// System.Console.WriteLine($"System.Runtime.InteropServices.RuntimeInformation.RuntimeIdentifier: {System.Runtime.InteropServices.RuntimeInformation.RuntimeIdentifier}");
// <-- Keep this information secure! -->
#if comments
System.Console.WriteLine("Environment Variables:");
foreach (System.Collections.DictionaryEntry de in System.Environment.GetEnvironmentVariables())
{
System.Console.WriteLine("{0} = {1}", de.Key, de.Value);
}
#endif
}
}
/*************************************************************************************************************************/
// NB
// default
// CS 8 Nullable reference type
// <Nullable>enable</Nullable> in .csproj
// CS 10 Implicit using directives
// <ImplicitUsings>enable</ImplicitUsings> in .csproj
// % dotnet run --configuration Debug
// % cat obj/Debug/net9.0/CS13.GlobalUsings.g.cs
// Or
// % dotnet run --configuration Release
// % cat obj/Release/net9.0/CS13.GlobalUsings.g.cs
/*
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
*/
// NB
// <AllowUnsafeBlocks>true</AllowUnsafeBlocks> in .csproj
// dotnet run
/*
Environment Properties
System.Environment.OSVersion: Unix 6.6.50.5083
System.Environment.OSVersion.Platform: Unix
System.Environment.OSVersion.Version: 6.6.50.5083
System.Environment.OSVersion.VersionString: Unix 6.6.50.5083
System.Environment.OSVersion.Version.Major: 6
System.Environment.OSVersion.Version.Minor: 6
System.Environment.OSVersion.Platform == System.PlatformID.Win32NT: False
System.Environment.OSVersion.Platform == System.PlatformID.Unix: True
System.Environment.Version: 9.0.1
System.Environment.Is64BitOperatingSystem: True
System.Environment.Is64BitProcess: True
System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription: .NET 9.0.1
System.Runtime.InteropServices.RuntimeInformation.ProcessArchitecture: X64
System.Runtime.InteropServices.RuntimeInformation.OSArchitecture: X64
System.Runtime.InteropServices.RuntimeInformation.OSDescription): Debian GNU/Linux 12 (bookworm)
1. params collections
Overload Resolution: Array
params string[] names: Zeta, Eta, Theta, Iota, Kappa
Overload Resolution: Anonymous Array
params string[] names: Lambda, Mu, Nu, Xi, Omicron
Most Efficient Overload Resolution : ReadOnlySpan
params List<string?> names: Phi, Chi, Psi, Omega
Overload Resolution: IEnumerable
params IEnumerable<string?> names: Lambda, Nu, Omicron, Rho, Tau
Overload Resolution: Linq
params IEnumerable<string?> names: Mu, Xi, Pi, Sigma, Upsilon
2. lock object
Type: System.Object
Type: System.Threading.Lock
3. Escape sequence \e
This is a bold text
This is a bold text
4. Method group natural type improvements
Id: 0, Name: Name
5. Implicit index access
Index from the end in initializers: 0, 111, 0, 0, 444
Index from the end in initializers: 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
6. ref and unsafe in iterators and async methods
Alpha, Beta, Gamma, , , Delta, , , Epsilon, , , Beta, , , , Zeta, Eta, Zeta
1, 2, 3, 4, 5, , , 2, , 6, 7, 6
A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z
A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z
7. allows ref struct
Span<int>: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
rajanipixelbook@penguin:~/R/CS/CS$ dotnet run
Environment Properties
System.Environment.OSVersion: Unix 6.6.50.5083
System.Environment.OSVersion.Platform: Unix
System.Environment.OSVersion.Version: 6.6.50.5083
System.Environment.OSVersion.VersionString: Unix 6.6.50.5083
System.Environment.OSVersion.Version.Major: 6
System.Environment.OSVersion.Version.Minor: 6
System.Environment.OSVersion.Platform == System.PlatformID.Win32NT: False
System.Environment.OSVersion.Platform == System.PlatformID.Unix: True
System.Environment.Version: 9.0.1
System.Environment.Is64BitOperatingSystem: True
System.Environment.Is64BitProcess: True
System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription: .NET 9.0.1
System.Runtime.InteropServices.RuntimeInformation.ProcessArchitecture: X64
System.Runtime.InteropServices.RuntimeInformation.OSArchitecture: X64
System.Runtime.InteropServices.RuntimeInformation.OSDescription): Debian GNU/Linux 12 (bookworm)
1. params collections
Overload Resolution: Array
params string[] names: Zeta, Eta, Theta, Iota, Kappa
Overload Resolution: Anonymous Array
params string[] names: Lambda, Mu, Nu, Xi, Omicron
Most Efficient Overload Resolution : ReadOnlySpan
params List<string?> names: Phi, Chi, Psi, Omega
Overload Resolution: IEnumerable
params IEnumerable<string?> names: Lambda, Nu, Omicron, Rho, Tau
Overload Resolution: Linq
params IEnumerable<string?> names: Mu, Xi, Pi, Sigma, Upsilon
2. lock object
Type: System.Object
Type: System.Threading.Lock
3. Escape sequence \e
This is a bold text
This is a bold text
4. Method group natural type improvements
Id: 0, Name: Name
5. Implicit index access
Index from the end in initializers: 0, 111, 0, 0, 444
Index from the end in initializers: 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
6. ref and unsafe in iterators and async methods
Alpha, Beta, Gamma, , , Delta, , , Epsilon, , , Beta, , , , Zeta, Eta, Zeta
1, 2, 3, 4, 5, , , 2, , 6, 7, 6
A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z
A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z
7. allows ref struct
Span<int>: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
Span<int>: 9, 7, 7, 8, 7, 1, 1, 2, 5, 10
8. ref struct interfaces
Cannot implement interface default/virtual default instance method for ref struct or readonly ref struct
Prior to CS 13, ref struct types weren't allowed to implement interfaces.
Beginning with CS 13, ref struct types including readonly ref struct types can implement interfaces.
To ensure ref safety rules, a ref struct type can't be converted to an interface type.
That is a boxing conversion, and could violate ref safety.
9. Partial properties
Pre-CS 13 Regex Method IsMatch("abc"): True
Pre-CS 13 Regex Method IsMatch("def"): True
Pre-CS 13 Regex Method IsMatch("xyz"): False
CS 13 Regex Property IsMatch("abc"): True
CS 13 Regex Property IsMatch("def"): True
CS 13 Regex Property IsMatch("xyz"): False
10. Overload resolution priority
sbyte called.
*/
// Credit
/*
https://dotnet.microsoft.com/
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment