[C#] 변수에 코드 할당

변수를 만들고 다음과 같은 코드 줄을 할당 할 수 있습니까?

ButtonClicked = (MessageBox.Show("Hello, World!"));

… 변수를 사용하면 코드 줄이 실행됩니다.



답변

다음 Action과 같이 할당 할 수 있습니다 .

var ButtonClicked = new Action(() => MessageBox.Show("hi"));

그런 다음 호출하십시오.

ButtonClicked();

완전성을 위해 (다양한 의견과 관련하여) …

Erik이 말했듯이 여러 줄의 코드를 실행할 수 있습니다.

var ButtonClicked = new Action(() =>
{
    MessageBox.Show("hi");

    MessageBox.Show("something else");  // something more useful than another popup ;)
});

Tim이 말했듯이 Action키워드를 생략 할 수 있습니다.

Action ButtonClicked = () => MessageBox.Show("hi");

Action ButtonClicked = () =>
{
    // multiple lines of code
};

KRyan의 주석을 처리하기 위해 비어있는 괄호와 관련하여 Action에 보낼 수있는 매개 변수 목록을 나타냅니다 (이 경우에는 없음) .

예를 들어 표시 할 메시지를 지정하려는 경우 “message”를 매개 변수로 추가 할 수 있습니다 ( 단일 문자열 매개 변수를 지정하기 위해로 변경 Action 했습니다 ) .Action<string>

Action<string> ButtonClicked = (message) => MessageBox.Show(message);

ButtonClicked("hello world!");


답변

귀하의 경우에는 delegate.

대리자가 어떻게 작동하는지 그리고 개념을 이해하여 더 쉬운 양식에 도달하는 방법을 살펴 보겠습니다.

// Create a normal function
void OnButtonClick()
{
    MessageBox.Show("Hello World!");
}
// Now we create a delegate called ButtonClick
delegate void ButtonClick();

델리게이트는 일반 함수의 형식을 취하지 만 인수가 없습니다 (다른 메서드와 마찬가지로 인수의 양을 제한 할 수 있지만 단순성을 위해 그렇지 않습니다).

이제 우리가 가진 것을 사용합시다. 다른 변수를 정의하는 것처럼 대리자를 정의합니다.

ButtonClick ButtonClicked = new ButtonClick(OnButtonClick);

기본적으로 ButtonClick (대리자) 유형을 갖는 ButtonClicked라는 새 변수를 만들었으며 사용시 OnButtonClick () 메서드에서 메서드를 실행합니다.
이를 사용하려면 다음을 호출하면됩니다.ButtonClicked();

따라서 전체 코드는 다음과 같습니다.

delegate void ButtonClick();

void OnButtonClick()
{
    MessageBox.Show("Hello World!");
}

void Foo()
{
    ButtonClick ButtonClicked = new ButtonClick(OnButtonClick);
    ButtonClicked(); // Execute the function.
}  

여기에서 람다 식으로 이동하여 상황에서 유용 할 수있는 방법을 확인할 수 있습니다.
.NET 라이브러리에 의해 이미 정의 된 많은 대리자가 있으며 일부는 매개 변수를 허용하지 않고 값을 반환하지 않는 Action과 같습니다. 과 같이 정의된다 public delegate void Action();
당신은 항상 새로운 위임마다 정의의 필요성 대신 여러분의 필요에 사용할 수 있습니다. 예를 들어 이전 컨텍스트에서 방금 작성했을 수 있습니다.

Action ButtonClicked = new Action(OnButtonClick);
ButtonClicked();

같은 일을했을 것입니다.
이제 대리자를 사용하는 다양한 방법을 보았으므로 첫 번째 람다 식을 사용하겠습니다. Lambda 표현식은 익명 함수입니다. 그래서 그들은 정상적인 기능이지만 이름이 없습니다. 다음과 같은 형태입니다.

x => DoSomethingWithX(x);
(x) => DoSomethingWithX(x);
(x,y) => DoSometingWithXY(x,y);
() => Console.WriteLine("I do not have parameters!");

이 경우에는 매개 변수가 없으므로 마지막 표현식을 사용합니다. 이것을 OnButtonClick 함수로 사용할 수 있지만 명명 된 함수가 없다는 이점이 있습니다. 대신 다음과 같이 할 수 있습니다.

Action ButtonClicked = new Action( () => MessageBox.Show("Hello World!") );

또는 더 쉽게

Action ButtonClicked = () => MessageBox.Show("Hello World!");

그런 다음 단순히 전화하십시오 ButtonClicked();물론 여러 줄의 코드를 가질 수도 있지만 더 이상 혼동하고 싶지 않습니다. 그래도 다음과 같이 보일 것입니다.

Action ButtonClicked = () =>
{
    MessageBox.Show("Hello World!");
};
ButtonClicked();

예를 들어 다음과 같은 함수를 실행할 수도 있습니다.

new Action(() => MessageBox.Show("Hello World!"))();

긴 게시물에 대해 죄송합니다. 너무 혼란스럽지 않았기를 바랍니다. 🙂

편집 : 자주 사용되지는 않지만 람다 식을 더 쉽게 이해할 수있는 대체 형식을 언급하는 것을 잊었습니다.

new Action(delegate() {
    Console.WriteLine("I am parameterless");
})();

또한 제네릭 사용 :

// Defines a delegate that has one parameter of type string. You could pass as many parameters as you want.
new Action<string>(delegate(string x) {
    Console.WriteLine(x);
})("I am a string parameter!");

차례로 람다 식을 사용할 수 있지만 매개 변수 유형을 정의 할 필요가 없습니다 (경우에 따라 경우도 있음). 예를 들어 위의 코드는 다음과 같이 간단하게 작성할 수 있습니다.

new Action<string>(x => {
    Console.WriteLine(x);
})("I am a string parameter!");

또는:

new Action<string>(x => Console.WriteLine(x))("I am a string parameter!");

EDIT2는 :
Action<string>의 표현이되는 public void delegate Action(string obj);
Action<string,string>표현이다 public void delegate Action(string obj, string obj2);
일반적 Action<T>표현 인public void delegate Action<T>(T obj);

EDIT3 : 게시물이 잠시 여기에 있었다는 것을 알고 있지만 이것은 언급하지 않아도 정말 멋지다고 생각합니다. 대부분의 질문과 관련된이 작업을 수행 할 수 있습니다.

dynamic aFunction = (Func<string, DialogResult>)MessageBox.Show;
aFunction("Hello, world!");

또는 간단히 :

Func<string, DialogResult> aFunction = MessageBox.Show;
aFunction("Hello, world!");


답변

Lazy클래스는 사용자가 요청할 때까지 계산되지 않는 값을 나타내도록 특별히 설계되었습니다. 구성 방법을 정의하는 메서드를 제공하여 구성하지만, 해당 메서드를 한 번만 실행하고 (값을 요청하는 여러 스레드가있는 경우에도) 추가 요청에 대해 이미 구성된 값을 반환합니다.

var foo = new Lazy<DialogResult>(()=>MessageBox.Show("Hello, World!"));

var result = foo.Value;


답변

내가 귀하의 질문을 읽는 방식은 GUI 컨트롤의 맥락에 있습니까?

이것이 WPF에있는 경우 컨트롤에서 명령을 처리하는 “올바른”방법을 살펴보십시오.
http://msdn.microsoft.com/en-us/library/ms752308(v=vs.110).aspx

…하지만 그것은 고통과 과잉 일 수 있습니다. 더 간단한 일반적인 경우에는 다음과 같은 이벤트 핸들러를 찾을 수 있습니다.

myButton.Click += (o, e) => MessageBox.Show("Hello, World!");

해당 이벤트 핸들러는 다양한 방법으로 처리 할 수 ​​있습니다. 위의 예는 익명 함수를 사용하지만 다음과 같이 할 수도 있습니다.

Action<object, RoutedEventArgs> sayHello = (o, e) => MessageBox.Show("Hello, World");
myButton.Click += new RoutedEventHandler(sayHello);

… 당신이 요청한 것처럼, 변수로 할당 된 함수 (또는 여기서 “Action”은 void를 반환하기 때문에).


답변

C # 코드를 변수에 할당하고 런타임에 컴파일하고 코드를 실행할 수 있습니다.

  • 코드 작성 :

    // Assign C# code to the code variable.
    string code = @"
    using System;
    
    namespace First
    {
        public class Program
        {
            public static void Main()
            {
                " +
                "Console.WriteLine(\"Hello, world!\");"
                + @"
            }
        }
    }
    ";
  • 컴파일러의 공급자 및 매개 변수를 만듭니다.

    CSharpCodeProvider provider = new CSharpCodeProvider();
    CompilerParameters parameters = new CompilerParameters();
  • 컴파일러의 매개 변수를 정의하십시오.

    // Reference to System.Drawing library
    parameters.ReferencedAssemblies.Add("System.Drawing.dll");
    // True - memory generation, false - external file generation
    parameters.GenerateInMemory = true;
    // True - exe file generation, false - dll file generation
    parameters.GenerateExecutable = true;
  • 어셈블리 컴파일 :

    CompilerResults results = provider.CompileAssemblyFromSource(parameters, code);
  • 오류 확인 :

    if (results.Errors.HasErrors)
    {
            StringBuilder sb = new StringBuilder();
    
            foreach (CompilerError error in results.Errors)
            {
                    sb.AppendLine(String.Format("Error ({0}): {1}", error.ErrorNumber, error.ErrorText));
            }
    
            throw new InvalidOperationException(sb.ToString());
    }
  • 어셈블리, 유형 및 Main 메서드를 가져옵니다.

    Assembly assembly = results.CompiledAssembly;
    Type program = assembly.GetType("First.Program");
    MethodInfo main = program.GetMethod("Main");
  • 실행 :

    main.Invoke(null, null);

참고:

http://www.codeproject.com/Tips/715891/Compiling-Csharp-Code-at-Runtime


답변