How to make inline functions in C#

C#.Net

C# Problem Overview


I'm using Linq To XML

new XElement("Prefix", Prefix == null ? "" : Prefix)

but I want to do some computation to the prefix before adding it to the xml, like eliminating spaces, special chars, some calculations etc

I don't want to create functions because this ones won't be of any help on any other part of my program but this, so is there any way to create inline functions??

C# Solutions


Solution 1 - C#

Yes, C# supports that. There are several syntaxes available.

  • Anonymous methods were added in C# 2.0:

      Func<int, int, int> add = delegate(int x, int y)
      {
          return x + y;
      };
      Action<int> print = delegate(int x)
      {
          Console.WriteLine(x);
      }
      Action<int> helloWorld = delegate // parameters can be elided if ignored
      {
          Console.WriteLine("Hello world!");
      }
    
  • Lambdas are new in C# 3.0 and come in two flavours.

    • Expression lambdas:

        Func<int, int, int> add = (int x, int y) => x + y; // or...
        Func<int, int, int> add = (x, y) => x + y; // types are inferred by the compiler
      
    • Statement lambdas:

        Action<int> print = (int x) => { Console.WriteLine(x); };
        Action<int> print = x => { Console.WriteLine(x); }; // inferred types
        Func<int, int, int> add = (x, y) => { return x + y; };
      
  • Local functions have been introduced with C# 7.0:

      int add(int x, int y) => x + y;
      void print(int x) { Console.WriteLine(x); }
    

There are basically two different types for these: Func and Action. Funcs return values but Actions don't. The last type parameter of a Func is the return type; all the others are the parameter types.

There are similar types with different names, but the syntax for declaring them inline is the same. An example of this is Comparison<T>, which is roughly equivalent to Func<T, T, int>.

Func<string, string, int> compare1 = (l,r) => 1;
Comparison<string> compare2 = (l, r) => 1;
Comparison<string> compare3 = compare1; // this one only works from C# 4.0 onwards

These can be invoked directly as if they were regular methods:

int x = add(23, 17); // x == 40
print(x); // outputs 40
helloWorld(x); // helloWorld has one int parameter declared: Action<int>
               // even though it does not make any use of it.

Solution 2 - C#

C# 7 adds support for local functions

Here is the previous example using a local function

void Method()
{
    string localFunction(string source)
    {
        // add your functionality here
        return source ;
    };

   // call the inline function
   localFunction("prefix");
}

Solution 3 - C#

The answer to your question is yes and no, depending on what you mean by "inline function". If you're using the term like it's used in C++ development then the answer is no, you can't do that - even a lambda expression is a function call. While it's true that you can define inline lambda expressions to replace function declarations in C#, the compiler still ends up creating an anonymous function.

Here's some really simple code I used to test this (VS2015):

	static void Main(string[] args)
	{
		Func<int, int> incr = a => a + 1;
		Console.WriteLine($"P1 = {incr(5)}");
	}

What does the compiler generate? I used a nifty tool called ILSpy that shows the actual IL assembly generated. Have a look (I've omitted a lot of class setup stuff)

This is the Main function:

		IL_001f: stloc.0
		IL_0020: ldstr "P1 = {0}"
		IL_0025: ldloc.0
		IL_0026: ldc.i4.5
		IL_0027: callvirt instance !1 class [mscorlib]System.Func`2<int32, int32>::Invoke(!0)
		IL_002c: box [mscorlib]System.Int32
		IL_0031: call string [mscorlib]System.String::Format(string, object)
		IL_0036: call void [mscorlib]System.Console::WriteLine(string)
		IL_003b: ret

See those lines IL_0026 and IL_0027? Those two instructions load the number 5 and call a function. Then IL_0031 and IL_0036 format and print the result.

And here's the function called:

		.method assembly hidebysig 
			instance int32 '<Main>b__0_0' (
				int32 a
			) cil managed 
		{
			// Method begins at RVA 0x20ac
			// Code size 4 (0x4)
			.maxstack 8

			IL_0000: ldarg.1
			IL_0001: ldc.i4.1
			IL_0002: add
			IL_0003: ret
		} // end of method '<>c'::'<Main>b__0_0'

It's a really short function, but it is a function.

Is this worth any effort to optimize? Nah. Maybe if you're calling it thousands of times a second, but if performance is that important then you should consider calling native code written in C/C++ to do the work.

In my experience readability and maintainability are almost always more important than optimizing for a few microseconds gain in speed. Use functions to make your code readable and to control variable scoping and don't worry about performance.

"Premature optimization is the root of all evil (or at least most of it) in programming." -- Donald Knuth

"A program that doesn't run correctly doesn't need to run fast" -- Me

Solution 4 - C#

Yes.

You can create anonymous methods or lambda expressions:

Func<string, string> PrefixTrimmer = delegate(string x) {
    return x ?? "";
};
Func<string, string> PrefixTrimmer = x => x ?? "";

Solution 5 - C#

You can use Func which encapsulates a method that has one parameter and returns a value of the type specified by the TResult parameter.

void Method()
{
    Func<string,string> inlineFunction = source => 
    {
        // add your functionality here
        return source ;
     };

 
    // call the inline function
   inlineFunction("prefix");
}

Solution 6 - C#

Not only Inside methods, it can be used inside classes also.

class Calculator
    {
        public static int Sum(int x,int y) => x + y;
        public static Func<int, int, int>  Add = (x, y) => x + y;
        public static Action<int,int> DisplaySum = (x, y) => Console.WriteLine(x + y);
    }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJoe DixonView Question on Stackoverflow
Solution 1 - C#R. Martinho FernandesView Answer on Stackoverflow
Solution 2 - C#DalSoftView Answer on Stackoverflow
Solution 3 - C#Ray FischerView Answer on Stackoverflow
Solution 4 - C#SLaksView Answer on Stackoverflow
Solution 5 - C#HomamView Answer on Stackoverflow
Solution 6 - C#Deepak MishraView Answer on Stackoverflow