.NET 8 Preview 2 Unveiled: 5 New Features You Need to Know💜
Tags: dotnet, csharp, news, beginners
Published: 2023-03-22 09:42:59

Microsoft has just launched the [.NET 8 Preview 2](https://devblogs.microsoft.com/dotnet/announcing-dotnet-8-preview-2/), introducing a host of new features that are sure to pique developers’ interest. In this post, we’ll delve into these new additions and improvements that this release brings to the .NET ecosystem.

## RequiredAttribute.DisallowAllDefaultValues\[\]

One of the first new features introduced in the .NET 8 preview 2 is the `RequiredAttribute.DisallowAllDefaultValues` functionality. The `RequiredAttribute` is used to mark a property or parameter as required, meaning it cannot be null.

With this new update, the `DisallowAllDefaultValues` property has been added to the `RequiredAttribute`, which allows validation that a struct does not equal its default value.

For instance, suppose we have a property in a class that is of type `Guid`. By default, a `Guid` is initialized to `Guid.Empty`. To ensure that the value of this property is always set, we can use the `Required` attribute with the `DisallowAllDefaultValues` property set to `true`.

If the value of this property is not explicitly set and it remains as `Guid.Empty`, the validation will fail, indicating that the value must be provided. [Here’s an example](https://devblogs.microsoft.com/dotnet/announcing-dotnet-8-preview-2/#requiredattribute-disallowalldefaultvalues) of how to use this functionality:

```csharp
public class MyClass
{
    [Required(DisallowAllDefaultValues = true)]
    public Guid MyGuidValue { get; set; }
}
```

In the above code, the `MyGuidValue` property is marked with the `Required` attribute, and the `DisallowAllDefaultValues` property is set to `true`. Therefore, the property will be validated to ensure that it is not equal to `Guid.Empty`. If the property is not set or is explicitly set to `Guid.Empty`, the validation will fail.

This feature is especially useful in scenarios where it is essential to ensure that the **value of a property or parameter is set explicitly** and cannot be left as its default value. It adds an extra layer of safety to the code and can help catch bugs early in the development cycle.

## RangeAttribute exclusive bounds

This feature allows users to specify exclusive bounds in their range validation using the `RangeAttribute`. With this, users can **define ranges with boundaries** that are excluded from validation.

To illustrate, [consider the following code example](https://devblogs.microsoft.com/dotnet/announcing-dotnet-8-preview-2/#rangeattribute-exclusive-bounds):

```csharp
[Range(0d, 1d, MinimumIsExclusive = true, MaximumIsExclusive = true)]
public double Sample { get; set; }
```

In this example, the `RangeAttribute` is applied to a `double` property called `Sample`. The attribute specifies that the valid range for `Sample` is any value greater than `0` and less than `1`. However, the boundary values `0` and `1` are excluded from the valid range.

By setting `MinimumIsExclusive` and `MaximumIsExclusive` to `true`, the `RangeAttribute` creates a range that is open at both ends, meaning that values that fall on the boundary of the range will fail validation. For instance, a value of `0` or `1` will not pass validation for the `Sample` property.

This is useful for scenarios where users want to **define a range that is open at both ends**, such as when defining probability values or ranges of values that cannot be exactly reached. Users can define more precise and nuanced validation rules for their data.

## LengthAttribute

Another improvement in .NET 8 preview 2 is an update to the `LengthAttribute`.

This attribute can now be used to **set both lower and upper bounds for strings or collections**, providing more flexibility in validation.

To use this updated attribute, simply specify the minimum and maximum allowed lengths as arguments to the `LengthAttribute`, as shown in the [following example](https://devblogs.microsoft.com/dotnet/announcing-dotnet-8-preview-2/#lengthattribute):

```csharp
[Length(10, 20)] // Require at least 10 elements and at most 20 elements.
public ICollection<int> Values { get; set; }
```

As you can see in the code example above, this ensures that the `Values` collection must contain at least 10 elements and no more than 20 elements. If the collection fails to meet either of these criteria, the validation will fail.

This is particularly useful in scenarios where developers need to **enforce specific length constraints on strings or collections** in their application. With the `LengthAttribute`, it’s now easier than ever to add this type of validation to your code.

## AllowedValuesAttribute and DeniedValuesAttribute

The following features that Microsoft presents are two new attributes that can be used for **validating a property** against a list of allowed or denied values.

These attributes are called `AllowedValuesAttribute` and `DeniedValuesAttribute`.

-   `AllowedValuesAttribute` specifies a list of allowed values
-   `DeniedValuesAttribute` specifies a list of denied values.

Here’s an [example of how to use these attributes](https://devblogs.microsoft.com/dotnet/announcing-dotnet-8-preview-2/#allowedvaluesattribute-and-deniedvaluesattribute):

```csharp
[AllowedValues("chocolate", "vanilla", "strawberry")]
public string IceCreamFlavor { get; set; }

[DeniedValues("beetroot", "eggplant", "rutabaga")]
public string CakeFlavor { get; set; }
```

In this example, the `IceCreamFlavor` property can only be set to “chocolate”, “vanilla”, or “strawberry”, while the `CakeFlavor` property cannot be set to “beetroot”, “eggplant”, or “rutabaga”. If the property is set to a value not in the allowed list or in the denied list, the validation will fail.

These attributes can be useful in scenarios where you want to **restrict the possible values of a property**, such as in a dropdown list or a set of checkboxes.

## System.Reflection Enhancements

Microsoft added [support for obtaining function pointer metadata via Reflection in .NET 8 Preview 2](https://devblogs.microsoft.com/dotnet/announcing-dotnet-8-preview-2/#system-reflection-introspection-support-for-function-pointers). This feature allows developers to **obtain parameter types, return type, and calling conventions for function pointers**. Previously, only the `IntPtr` type was used for function pointers, which made obtaining function pointer metadata difficult.

The new functionality is currently available in the CoreCLR runtime and in `MetadataLoadContext`. Support for the Mono and NativeAOT runtimes is expected later.

Here’s an example using reflection:

```csharp
FieldInfo fieldInfo = typeof(MyClass).GetField(nameof(MyClass._fp));
Type fpType = fieldInfo.FieldType;

Console.WriteLine(fpType.IsFunctionPointer); // True
Console.WriteLine(fpType.IsUnmanagedFunctionPointer); // True

Console.WriteLine($"Return type: {fpType.GetFunctionPointerReturnType()}");
foreach (Type parameterType in fpType.GetFunctionPointerParameterTypes())
{
    Console.WriteLine($"Parameter type: {parameterType}");
}

Type modifiedType = fieldInfo.GetModifiedFieldType();
Type normalType = modifiedType.UnderlyingSystemType;

foreach (Type callConv in modifiedType.GetFunctionPointerCallingConventions())
{
    Console.WriteLine($"Calling convention: {callConv}");
}

foreach (Type modreq in modifiedType.GetFunctionPointerParameterTypes()[0].GetRequiredCustomModifiers())
{
    Console.WriteLine($"Required modifier for first parameter: {modreq }");
}

public unsafe class MyClass
{
    public delegate* unmanaged[Cdecl, SuppressGCTransition]<in int, void> _fp;
}
```

This feature supports parameterized types such as generics, pointers, and arrays, including an array of function pointers. The `Type.ElementType` property and the `Type.GetGenericArguments()` method can be used to obtain further types which ultimately may be a function pointer.

As .NET 8 continues to evolve, we can expect to see even more advancements in the platform that will allow developers to build powerful and efficient applications. What are your thoughts on the future of .NET 8 and the direction in which Microsoft is taking the platform?