Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the ?[]? syntax in C#?

While I was studying the delegate which is actually an abstract class in Delegate.cs, I saw the following method in which I don't understand

  • Why the return value uses ? though it's already a reference(class) type
  • ?[]? meaning on the parameter

Could you explain?

public static Delegate? Combine(params Delegate?[]? delegates)
{
    if (delegates == null || delegates.Length == 0)
        return null;

    Delegate? d = delegates[0];
    for (int i = 1; i < delegates.Length; i++)
        d = Combine(d, delegates[i]);

    return d;
}
like image 693
snr Avatar asked Dec 29 '19 11:12

snr


People also ask

What is basic syntax in C?

The C basic syntax consists of header files, main function, and program code. This is the most fundamental structure in the C program. A C program necessarily consists of the main function because the execution of the program starts from this line. Without the main function, the program execution does not start.

What Is syntax in C with example?

The syntax of the C programming language is the set of rules governing writing of software in the C language. It is designed to allow for programs that are extremely terse, have a close relationship with the resulting object code, and yet provide relatively high-level data abstraction.

What is the syntax of a program?

Syntax is the set of rules that define what the various combinations of symbols mean. This tells the computer how to read the code. Syntax refers to a concept in writing code dealing with a very specific set of words and a very specific order to those words when we give the computer instructions.

What is syntax error in C?

Syntax errors are mistakes in the source code, such as spelling and punctuation errors, incorrect labels, and so on, which cause an error message to be generated by the compiler.


3 Answers

Step by step explanation:

params Delegate?[] delegates - It is an array of nullable Delegate

params Delegate?[]? delegates - The entire array can be nullable

Since each parameter is of the type Delegate? and you return an index of the Delegate?[]? array, then it makes sense that the return type is Delegate? otherwise the compiler would return an error as if you were returing and int from a method that returns a string.

You could change for instance your code to return a Delegate type like this:

public static Delegate Combine(params Delegate?[]? delegates)
{
    Delegate defaulDelegate = // someDelegate here
    if (delegates == null || delegates.Length == 0)
        return defaulDelegate;

    Delegate d = delegates[0] ?? defaulDelegate;
    for (int i = 1; i < delegates.Length; i++)
        d = Combine(d, delegates[i]);

    return d;
}
like image 143
Athanasios Kataras Avatar answered Oct 11 '22 23:10

Athanasios Kataras


Nullable Reference Types are new in C# 8.0, they do not exist before.

It's a matter of documentation, and how warnings at compile-time are produced.

The exception "object not set to an instance of an object" exception is quiet common. But this is a runtime exception, it can partially discovered at compile time already.

For a regulate Delegate d you can always call

 d.Invoke();

meaning, you can code it, at compile time nothing will happen. It may raise exceptions at runtime.

While for a new Delegate? p this Code

 p.Invoke();

will produce a compiler warning. CS8602: Dereference of a possibly null reference unless you write:

 p?.Invoke();

what means, call only if not null.

So you document a variable may contain null or not. It raises warnings earlier and it can avoid multiple tests for null. The same what you have for int and int?. You know for sure, one is not null - and you know how to convert one to the other.

like image 38
Holger Avatar answered Oct 11 '22 23:10

Holger


In C# 8 one should explicitly mark reference types as nullable.

By default, those types are not able to contain null, kinda similar to value types. While this does not change how things work under the hood, the type checker will require you to do this manually.

Given code is refactored to work with C# 8, but it does not benefit from this new feature.

public static Delegate? Combine(params Delegate?[]? delegates)
{
    // ...[]? delegates - is not null-safe, so check for null and emptiness
    if (delegates == null || delegates.Length == 0)
        return null;

    // Delegate? d - is not null-safe too
    Delegate? d = delegates[0];
    for (int i = 1; i < delegates.Length; i++)
        d = Combine(d, delegates[i]);

    return d;
}

Here is an example of an updated code (not working, just an idea) leveraging this feature. It saved us from a null-check and simplified this method a bit.

public static Delegate? Combine(params Delegate[] delegates)
{
    // `...[] delegates` - is null-safe, so just check if array is empty
    if (delegates.Length == 0) return null;

    // `d` - is null-safe too, since we know for sure `delegates` is both not null and not empty
    Delegate d = delegates[0];

    for (int i = 1; i < delegates.Length; i++)
        // then here is a problem if `Combine` returns nullable
        // probably, we can add some null-checks here OR mark `d` as nullable
        d = Combine(d, delegates[i]);

    return d;
}
like image 5
amankkg Avatar answered Oct 12 '22 00:10

amankkg