What Does This C# Code with an "Arrow" Mean and How Is It Called

What does this C# code with an arrow (=, an equal sign and greater than sign) mean and how is it called?

That is a lambda expression. It is a very special anonymous delegate. Basically you are defining a method and not giving a name. Its parameters are to the left of the => and the method body is to the right of the =>. In your particular case,

(se, cert, chain, sslerror) => { return true; };

is an anonymous method defined by a lambda expression. This particular method has four parameters

object se
X509Certificate cert
X509Chain chain
SslPolicyErrors sslerror

and the method body is

return true;

It's as if you had said

class ServerCertificateValidation {
public bool OnRemoteCertificateValidation(
object se,
X509Certificate cert,
X509Chain chain,
SslPolicyErrors sslerror
) {
return true;
}
}

and then

var validation = new ServerCertificateValidation();
System.Net.ServicePointManager.ServerCertificateValidationCallback +=
validation.OnRemoteCertificateValidation;

How is that (blah,blah,blah)=>{return true;} construct called and where can I find more info on such constructs?

It's called the same way that any other method is called. For example, you can do this:

Func<int, int, int> adder = (m, n) => m + n;

Here I am defining a method that eats a pair of int and returns an int. That int is obtained by adding the values of the input parameters. It can be invoked like any other method.

int four = adder(2, 2); 

Here's an article on MSDN on lambda expressions and an article on the lambda operator. If you're really interested, the name comes from lambda calculus.

What's the meaning of = (an arrow formed from equals & greater than) in JavaScript?

What It Is

This is an arrow function. Arrow functions are a short syntax, introduced by ECMAscript 6, that can be used similarly to the way you would use function expressions. In other words, you can often use them in place of expressions like function (foo) {...}. But they have some important differences. For example, they do not bind their own values of this (see below for discussion).

Arrow functions are part of the ECMAscript 6 specification. They are not yet supported in all browsers, but they are partially or fully supported in Node v. 4.0+ and in most modern browsers in use as of 2018. (I’ve included a partial list of supporting browsers below).

You can read more in the Mozilla documentation on arrow functions.

From the Mozilla documentation:

An arrow function expression (also known as fat arrow function) has a shorter syntax compared to function expressions and lexically binds the this value (does not bind its own this, arguments, super, or new.target). Arrow functions are always anonymous. These function expressions are best suited for non-method functions and they can not be used as constructors.

A Note on How this Works in Arrow Functions

One of the most handy features of an arrow function is buried in the text above:

An arrow function... lexically binds the this value (does not bind its own this...)

What this means in simpler terms is that the arrow function retains the this value from its context and does not have its own this. A traditional function may bind its own this value, depending on how it is defined and called. This can require lots of gymnastics like self = this;, etc., to access or manipulate this from one function inside another function. For more info on this topic, see the explanation and examples in the Mozilla documentation.

Example Code

Example (also from the docs):

var a = [
"We're up all night 'til the sun",
"We're up all night to get some",
"We're up all night for good fun",
"We're up all night to get lucky"
];

// These two assignments are equivalent:

// Old-school:
var a2 = a.map(function(s){ return s.length });

// ECMAscript 6 using arrow functions
var a3 = a.map( s => s.length );

// both a2 and a3 will be equal to [31, 30, 31, 31]


Notes on Compatibility

You can use arrow functions in Node, but browser support is spotty.

Browser support for this functionality has improved quite a bit, but it still is not widespread enough for most browser-based usages. As of December 12, 2017, it is supported in current versions of:

  • Chrome (v. 45+)
  • Firefox (v. 22+)
  • Edge (v. 12+)
  • Opera (v. 32+)
  • Android Browser (v. 47+)
  • Opera Mobile (v. 33+)
  • Chrome for Android (v. 47+)
  • Firefox for Android (v. 44+)
  • Safari (v. 10+)
  • iOS Safari (v. 10.2+)
  • Samsung Internet (v. 5+)
  • Baidu Browser (v. 7.12+)

Not supported in:

  • IE (through v. 11)
  • Opera Mini (through v. 8.0)
  • Blackberry Browser (through v. 10)
  • IE Mobile (through v. 11)
  • UC Browser for Android (through v. 11.4)
  • QQ (through v. 1.2)

You can find more (and more current) information at CanIUse.com (no affiliation).

what is ASCII code for right filled arrow ►

You can easily convert char to int and thus obtain its code:

  char arrow = '►'; // Copy + Paste from the question

Console.Write($"{arrow} : {(int)arrow} : \\u{(int)arrow:X4}";);

Outcome:

  ► : 9658 : \u25BA

and that's why you can put

  char arrow = '\u25BA';

What does the '=' syntax in C# mean?

It's the lambda operator.

From C# 3 to C# 5, this was only used for lambda expressions. These are basically a shorter form of the anonymous methods introduced in C# 2, but can also be converted into expression trees.

As an example:

Func<Person, string> nameProjection = p => p.Name;

is equivalent to:

Func<Person, string> nameProjection = delegate (Person p) { return p.Name; };

In both cases you're creating a delegate with a Person parameter, returning that person's name (as a string).

In C# 6 the same syntax is used for expression-bodied members, e.g.

// Expression-bodied property
public int IsValid => name != null && id != -1;

// Expression-bodied method
public int GetHashCode() => id.GetHashCode();

See also:

  • What's the difference between anonymous methods (C# 2.0) and lambda expressions (C# 3.0)
  • What is a Lambda?
  • C# Lambda expression, why should I use this?

(And indeed many similar questions - try the lambda and lambda-expressions tags.)

usage and explanation of = syntax

can anyone explain about what the usage of => syntax?

The "fat arrow" syntax is used to form something called a Lambda Expression in C#. It is a mere syntactical sugar for a delegates creation.

The expression you provided doesn't make any sense, but you can see it used alot in LINQ:

var strings = new[] { "hello", "world" };
strings.Where(x => x.Contains("h"));

The syntax x => x.Contains("h") will be inferred by the compiler as a Func<string, bool> which will be generated during compile time.


Edit:

If you really want to see whats going on "behind the scenes", you can take a look at the decompiled code inside any .NET decompiler:

[CompilerGenerated]
private static Func<string, bool> CS$<>9__CachedAnonymousMethodDelegate1;

private static void Main(string[] args)
{
string[] strings = new string[]
{
"hello",
"world"
};

IEnumerable<string> arg_3A_0 = strings;
if (Program.CS$<>9__CachedAnonymousMethodDelegate1 == null)
{
Program.CS$<>9__CachedAnonymousMethodDelegate1 = new Func<string, bool>
(Program.<Main>b__0);
}
arg_3A_0.Where(Program.CS$<>9__CachedAnonymousMethodDelegate1);
}

[CompilerGenerated]
private static bool <Main>b__0(string x)
{
return x.Contains("h");
}

You can see here that the compiler created a cached delegate of type Func<string, bool> called Program.CS$<>9__CachedAnonymousMethodDelegate1 and a named method called <Main>b__0 which get passed to the Where clause.

What does the first arrow operator in this FuncT, TReturn mean?

What does the first arrow operator mean?

In newer versions of C#, you are allowed to write:

int M(int x) 
{
return x + x;
}

as the shorter and clearer:

int M(int x) => x + x;

It is nothing more than a "syntactic sugar" that lets you write a simple method in a shorter and more direct way.

it does not look like an expression body or a lambda operator.

The left => indicates an expression body. The right => indicates a lambda. So it is somewhat confusing in your example because the thing being returned is a lambda, which also uses =>. But do not let that distract you:

Func<int, int> M() => x => x + 1;

is just a short way of writing

Func<int, int> M() 
{
return x => x + 1;
}

Which in turn is just a short way or writing

static int Anonymous(int x)
{
return x + 1;
}
Func<int, int> M()
{
return Anonymous;
}

If you find code with multiple => operators confusing you can always remove them by desugaring them into the more explicit form. It's just a short form that some people find easier to read.


Can you please write

static Func<op, int> combo(string head, double tail) =>
(op op) => ...;

with just one => operator.

Sure. Here are two equivalent ways to write that code.

// Block body, lambda return.
static Func<op, int> combo(string head, double tail)
{
return (op op) => ...;
}

// Block body, local function return:
static Func<op, int> combo(string head, double tail)
{
op MyFunction(op)
{
return ...;
}
return MyFunction;
}

Sorry, I was not being explicit. What I meant was can you please extract the lambda into its own standalone function, like what one would do in the olden days.

Sure; that is a little more complicated. We will do it in a series of small steps:

We start with this:

Func<op, int> combo(string head, double tail) => 
(op op) =>
op == op.add ? Int32.Parse(head) + Convert.ToInt32(tail) :
Int32.Parse(head) - Convert.ToInt32(tail);

Desugar the outer function:

Func<op, int> combo(string head, double tail)
{
return (op op) =>
op == op.add ? Int32.Parse(head) + Convert.ToInt32(tail) :
Int32.Parse(head) - Convert.ToInt32(tail);
}

Turn the inner function into a helper:

static int Helper(string head, double tail, op op)
{
return op == op.add ? Int32.Parse(head) + Convert.ToInt32(tail) :
Int32.Parse(head) - Convert.ToInt32(tail);
}

Func<op, int> combo(string head, double tail)
{
return (op op) => Helper(head, tail, op);
}

Now move the helper method to a class:

private class Closure
{
public int Helper(string head, double tail, op op)
{
return op == op.add ? Int32.Parse(head) + Convert.ToInt32(tail) :
Int32.Parse(head) - Convert.ToInt32(tail);
}
}

Func<op, int> combo(string head, double tail)
{
Closure c = new Closure();
return (op op) => c.Helper(head, tail, op);
}

Now make head and tail members of closure:

private class Closure
{
public string head;
public double tail;
public int Helper(op op)
{
return op == op.add ? Int32.Parse(head) + Convert.ToInt32(tail) :
Int32.Parse(head) - Convert.ToInt32(tail);
}
}

Func<op, int> combo(string head, double tail)
{
Closure c = new Closure();
c.head = head;
c.tail = tail;
return (op op) => c.Helper(op);
}

And now we can desugar the lambda:

private class Closure
{
public string head;
public double tail;
public int Helper(op op)
{
return op == op.add ? Int32.Parse(head) + Convert.ToInt32(tail) :
Int32.Parse(head) - Convert.ToInt32(tail);
}
}

Func<op, int> combo(string head, double tail)
{
Closure c = new Closure();
c.head = head;
c.tail = tail;
return c.Helper;
}

And we're done.

If you decompile your code using ILDASM or sharplab.io or some such tool you will discover that this is exactly what the compiler generates for your code, except that it generates weird, illegal names for the helpers to ensure that you never accidentally call one of them by mistake.

Arrow operator (-) usage in C

foo->bar is equivalent to (*foo).bar, i.e. it gets the member called bar from the struct that foo points to.

What does the = operator mean in a property?

What you're looking at is an expression-bodied member not a lambda expression.

When the compiler encounters an expression-bodied property member, it essentially converts it to a getter like this:

public int MaxHealth
{
get
{
return Memory[Address].IsValid ? Memory[Address].Read<int>(Offs.Life.MaxHp) : 0;
}
}

(You can verify this for yourself by pumping the code into a tool called TryRoslyn.)

Expression-bodied members - like most C# 6 features - are just syntactic sugar. This means that they don’t provide functionality that couldn't otherwise be achieved through existing features. Instead, these new features allow a more expressive and succinct syntax to be used

As you can see, expression-bodied members have a handful of shortcuts that make property members more compact:

  • There is no need to use a return statement because the compiler can infer that you want to return the result of the expression
  • There is no need to create a statement block because the body is only one expression
  • There is no need to use the get keyword because it is implied by the use of the expression-bodied member syntax.

I have made the final point bold because it is relevant to your actual question, which I will answer now.

The difference between...

// expression-bodied member property
public int MaxHealth => x ? y:z;

And...

// field with field initializer
public int MaxHealth = x ? y:z;

Is the same as the difference between...

public int MaxHealth
{
get
{
return x ? y:z;
}
}

And...

public int MaxHealth = x ? y:z;

Which - if you understand properties - should be obvious.

Just to be clear, though: the first listing is a property with a getter under the hood that will be called each time you access it. The second listing is is a field with a field initializer, whose expression is only evaluated once, when the type is instantiated.

This difference in syntax is actually quite subtle and can lead to a "gotcha" which is described by Bill Wagner in a post entitled "A C# 6 gotcha: Initialization vs. Expression Bodied Members".

While expression-bodied members are lambda expression-like, they are not lambda expressions. The fundamental difference is that a lambda expression results in either a delegate instance or an expression tree. Expression-bodied members are just a directive to the compiler to generate a property behind the scenes. The similarity (more or less) starts and end with the arrow (=>).

I'll also add that expression-bodied members are not limited to property members. They work on all these members:

  • Properties
  • Indexers
  • Methods
  • Operators

Added in C# 7.0

  • Constructors
  • Finalizers

However, they do not work on these members:

  • Nested Types
  • Events
  • Fields

Underscore Arrow (_ = ...) What Is This?

It's just a lambda expression that uses _ instead of x for its parameter. _ is a valid identifier so it can be used as a parameter name.

As mentioned in the comments, it's a convention among some developers to call it _ to indicate that it's not actually used by the lambda expression, but it's no more than that: a convention.

Note that this is not the same thing as a discard (introduced several years after this answer), which is a special variable for assigning values that aren't going to be used and will instead be discarded. Unlike discarded values, _ parameters continue to exist in lambda scope; they just aren't used anywhere in the lambda expression. And there can only be one _ in scope at a time.



Related Topics



Leave a reply



Submit