use*_*673 646 .net c# methods delegates
我有几个方法都具有相同的签名(参数和返回值),但不同的名称和方法的内部是不同的.我想传递方法的名称以运行到另一个将调用传入方法的方法.
public int Method1(string)
{
... do something
return myInt;
}
public int Method2(string)
{
... do something different
return myInt;
}
public bool RunTheMethod([Method Name passed in here] myMethodName)
{
... do stuff
int i = myMethodName("My String");
... do more stuff
return true;
}
public bool Test()
{
return RunTheMethod(Method1);
}
Run Code Online (Sandbox Code Playgroud)
此代码不起作用,但这是我想要做的.我不明白的是如何编写RunTheMethod代码,因为我需要定义参数.
Egi*_*sen 796
您可以使用.net 3.5中的Func委托作为RunTheMethod方法中的参数.Func委托允许您指定一个方法,该方法接受特定类型的多个参数并返回特定类型的单个参数.这是一个应该工作的例子:
public class Class1
{
public int Method1(string input)
{
//... do something
return 0;
}
public int Method2(string input)
{
//... do something different
return 1;
}
public bool RunTheMethod(Func<string, int> myMethodName)
{
//... do stuff
int i = myMethodName("My String");
//... do more stuff
return true;
}
public bool Test()
{
return RunTheMethod(Method1);
}
}
Run Code Online (Sandbox Code Playgroud)
Jon*_*eet 345
您需要使用委托.在这种情况下,所有方法都接受一个string
参数并返回int
- 这最简单地由Func<string, int>
委托1表示.因此,您的代码可以通过简单的更改变得正确:
public bool RunTheMethod(Func<string, int> myMethodName)
{
// ... do stuff
int i = myMethodName("My String");
// ... do more stuff
return true;
}
Run Code Online (Sandbox Code Playgroud)
诚然,代表们拥有比这更多的权力.例如,使用C#,您可以从lambda表达式创建委托,因此您可以这样调用您的方法:
RunTheMethod(x => x.Length);
Run Code Online (Sandbox Code Playgroud)
这将创建一个这样的匿名函数:
// The <> in the name make it "unspeakable" - you can't refer to this method directly
// in your own code.
private static int <>_HiddenMethod_<>(string x)
{
return x.Length;
}
Run Code Online (Sandbox Code Playgroud)
然后将该委托传递给该RunTheMethod
方法.
您可以使用委托进行事件订阅,异步执行,回调 - 各种事情.非常值得阅读它们,特别是如果你想使用LINQ.我有一个文章是大多是关于委托和事件之间的差异,但你会发现它很有用呢.
1这只是基于Func<T, TResult>
框架中的通用委托类型; 你可以轻松宣布自己的:
public delegate int MyDelegateType(string value)
Run Code Online (Sandbox Code Playgroud)
然后使参数成为类型MyDelegateType
.
Zai*_*Ali 104
从OP的例子来看:
public static int Method1(string mystring)
{
return 1;
}
public static int Method2(string mystring)
{
return 2;
}
Run Code Online (Sandbox Code Playgroud)
你可以试试Action Delegate!然后使用调用您的方法
public bool RunTheMethod(Action myMethodName)
{
myMethodName(); // note: the return value got discarded
return true;
}
RunTheMethod(() => Method1("MyString1"));
Run Code Online (Sandbox Code Playgroud)
要么
public static object InvokeMethod(Delegate method, params object[] args)
{
return method.DynamicInvoke(args);
}
Run Code Online (Sandbox Code Playgroud)
然后简单地调用方法
Console.WriteLine(InvokeMethod(new Func<string,int>(Method1), "MyString1"));
Console.WriteLine(InvokeMethod(new Func<string, int>(Method2), "MyString2"));
Run Code Online (Sandbox Code Playgroud)
kra*_*s88 30
public static T Runner<T>(Func<T> funcToRun)
{
//Do stuff before running function as normal
return funcToRun();
}
Run Code Online (Sandbox Code Playgroud)
用法:
var ReturnValue = Runner(() => GetUser(99));
Run Code Online (Sandbox Code Playgroud)
Bru*_*eis 12
你应该使用一个Func<string, int>
委托,它代表一个带有string
as参数的函数并返回一个int
:
public bool RunTheMethod(Func<string, int> myMethod) {
// do stuff
myMethod.Invoke("My String");
// do stuff
return true;
}
Run Code Online (Sandbox Code Playgroud)
然后使用它:
public bool Test() {
return RunTheMethod(Method1);
}
Run Code Online (Sandbox Code Playgroud)
为了尽可能完整地分享解决方案,我最终会提出三种不同的做法,但现在我将从最基本的原则开始.
所有CLR(公共语言运行时)语言(例如C#和Visual Basic)都在名为CLI(公共语言解释器)的VM下工作,该公司运行代码的级别高于C和C++等本地语言(直接编译为机器代码) .因此,方法不是任何类型的编译块,但它们只是CLR识别并用于拉出它们的主体并将其重新转换为机器代码的内联指令的结构化元素.因此,您无法将方法作为参数传递,因为方法本身不会产生任何值:它不是有效的表达式!所以,你将绊倒代表概念.
委托表示指向方法的指针.由于(如上所述)方法不是值,因此CLR语言中有一个特殊的类:Delegate
.该类包装任何方法,您可以隐式地将任何方法强制转换为该方法.
请看以下用法示例:
static void MyMethod()
{
Console.WriteLine("I was called by the Delegate special class!");
}
static void CallAnyMethod(Delegate yourMethod)
{
yourMethod.DynamicInvoke(new object[] { /*Array of arguments to pass*/ });
}
static void Main()
{
CallAnyMethod(MyMethod);
}
Run Code Online (Sandbox Code Playgroud)
方法1直接
使用Delegate
特殊类作为上例.此解决方案的问题是,在动态传递参数时,将取消选中代码,而不会将它们限制为方法声明中的类型.
方式2/3
除了Delegate
特殊类之外,委托概念扩展到自定义委托,它们是delegate
关键字前面的方法声明,它们的行为类似于普通方法.他们如此检查,你会得到一个" 完美 "的代码.
请看以下示例:
delegate void PrintDelegate(string prompt);
static void PrintSomewhere(PrintDelegate print, string prompt)
{
print(prompt);
}
static void PrintOnConsole(string prompt)
{
Console.WriteLine(prompt);
}
static void PrintOnScreen(string prompt)
{
MessageBox.Show(prompt);
}
static void Main()
{
PrintSomewhere(PrintOnConsole, "Press a key to get a message");
Console.Read();
PrintSomewhere(PrintOnScreen, "Hello world");
}
Run Code Online (Sandbox Code Playgroud)
通过这种方式不写自己的自定义委托的第二个选项是使用在系统库中声明的其中一个:
Action
包装a void
没有参数.Action<T1>
void
用一个参数包装一个.Action<T1, T2>
void
用两个参数包装一个.Func<TR>
包装一个TR
返回类型且没有参数的函数.Func<T1, TR>
使用TR
返回类型和一个参数包装函数.Func<T1, T2, TR>
使用TR
返回类型和两个参数包装函数.(后一种解决方案是许多人发布的.)
如果您希望能够在运行时更改调用哪个方法,我建议使用代理:http: //www.codeproject.com/KB/cs/delegates_step1.aspx
它允许您创建一个对象来存储要调用的方法,并且可以在需要时将其传递给其他方法.