[c#] C #에서 인라인 함수를 만드는 방법

Linq To XML을 사용하고 있습니다.

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

하지만 공백, 특수 문자, 일부 계산 등을 제거하는 것과 같이 접두사를 xml에 추가하기 전에 일부 계산을 수행하고 싶습니다.

이 함수는 내 프로그램의 다른 부분에 도움이되지 않기 때문에 함수를 만들고 싶지 않지만 이것은 인라인 함수를 만드는 방법이 있습니까 ??



답변

예, C #은이를 지원합니다. 사용 가능한 여러 구문이 있습니다.

  • 익명 메서드 가 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!");
    }
    
  • Lambda 는 C # 3.0의 새로운 기능이며 두 가지 유형으로 제공됩니다.

    • 식 람다 :

      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
      
    • 문 람다 :

      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; };
      
  • C # 7.0에는 로컬 함수 가 도입되었습니다.

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

이 이러한 두 가지 종류가 기본적으로 있습니다 : FuncAction. Funcs는 값을 반환하지만 Action그렇지 않습니다. a의 마지막 유형 매개 변수 Func는 반환 유형입니다. 나머지는 모두 매개 변수 유형입니다.

이름이 다른 유사한 유형이 있지만 인라인으로 선언하는 구문은 동일합니다. 이것의 예는 Comparison<T>, 대략 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

일반 메소드 인 것처럼 직접 호출 할 수 있습니다.

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.


답변

C # 7은 로컬 함수에 대한 지원을 추가 합니다.

다음은 로컬 함수를 사용한 이전 예입니다.

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

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


답변

귀하의 질문에 대한 대답은 “인라인 기능”이 의미하는 바에 따라 예 및 아니오입니다. C ++ 개발에서 사용되는 것과 같은 용어를 사용하는 경우 대답은 아니오입니다. 그렇게 할 수 없습니다. 심지어 람다 식도 함수 호출입니다. C #에서 함수 선언을 대체하기 위해 인라인 람다 식을 정의 할 수 있다는 것은 사실이지만 컴파일러는 여전히 익명 함수를 생성합니다.

다음은 이것을 테스트하는 데 사용한 매우 간단한 코드입니다 (VS2015).

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

컴파일러는 무엇을 생성합니까? 실제로 생성 된 IL 어셈블리를 보여주는 ILSpy라는 멋진 도구를 사용했습니다. 보세요 (많은 수업 설정 항목을 생략했습니다)

이것이 주요 기능입니다.

        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

IL_0026 및 IL_0027 줄이 보이십니까? 이 두 명령어는 숫자 5를로드하고 함수를 호출합니다. 그런 다음 IL_0031 및 IL_0036 형식을 지정하고 결과를 인쇄합니다.

다음은 호출 된 함수입니다.

        .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'

정말 짧은 기능이지만 기능입니다.

최적화를 위해 노력할 가치가 있습니까? 아니. 1 초에 수천 번 호출하고 있지만 성능이 그렇게 중요하다면 C / C ++로 작성된 네이티브 코드를 호출하여 작업을 수행하는 것을 고려해야합니다.

내 경험상 가독성과 유지 보수성은 몇 마이크로 초의 속도 향상을 최적화하는 것보다 거의 항상 더 중요합니다. 함수를 사용하여 코드를 읽기 쉽게 만들고 변수 범위를 제어하고 성능에 대해 걱정하지 마십시오.

“조기 최적화는 프로그래밍에서 모든 악 (또는 적어도 대부분)의 근원입니다.” -도널드 크 누스

“올바르게 실행되지 않는 프로그램은 빠르게 실행할 필요가 없습니다.”-Me


답변

예.

익명 메서드 또는 람다 식을 만들 수 있습니다 .

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


답변

하나의 매개 변수가있는 메소드를 캡슐화하고 TResult 매개 변수에 지정된 유형의 값을 리턴하는 Func 를 사용할 수 있습니다 .

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


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


답변

Inside 메서드뿐만 아니라 클래스 내부에서도 사용할 수 있습니다.

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);
    }


답변