我可以在方法中自引用,而不使用方法名称(出于代码维护原因,这可能会导致未来的错误)
void SelfRef(string _Input){
if (_Input == "route1"){
//route1 calls route 2
SelfRef("route2"); //call self
}else if (_Input == "route2"){
//route2 ends
}
}
我想不再写“SelfRef”这个词,让这个功能免受未来变化的影响?
答案 0 :(得分:7)
是的,有可能:
void Foo(int bar)
{
Console.WriteLine(bar);
if(bar < 10)
MethodBase.GetCurrentMethod().Invoke(this, new object[] {++bar});
else
Console.WriteLine("Finished");
}
但是请永远不要使用这样的代码(它很难看,它很慢,很难理解,如果方法是内联的,它将不起作用)。
由于您可能使用像Visual Studio这样的IDE,因此重命名方法永远不应成为问题;即使您手动重命名该方法,您可能会遇到编译时错误。
答案 1 :(得分:6)
我不想写下#34; SelfRef&#34;再次使功能免受未来变化的影响?
正如其他人所说,如果您打算重命名方法,则应该只使用重命名工具。
但是,制作一个不引用函数名称的递归函数是一个有趣的挑战。这是一种方法:
delegate Action<A> Recursive<A>(Recursive<A> r);
static Action<A> AnonymousRecursion<A>(Func<Action<A>, Action<A>> f)
{
Recursive<A> rec = r => a => { f(r(r))(a); };
return rec(rec);
}
Action<string> SelfRef = AnonymousRecursion<string>(
f =>
input =>
{
if (input == "route1")
f("route2");
// and so on
});
注意字段SelfRef
如何在其身体中引用SelfRef
,但递归非常简单;您只需递归f
而不是SelfRef
。
但是我告诉你,这个代码比简单地编写一个简单的递归方法更难以理解和维护。
答案 2 :(得分:2)
现在让我们清楚地说明“自我引用”的技术术语是递归。让我们开始研究这个问题。
您希望编写递归方法,但由于可维护性原因,不希望“提及”方法名称。当我看到这个时,我就像是,“你在用什么编辑器?”。可维护性原因?你的意思是当你更改代码中断方法的名称时?
使用IDE可以轻松解决这些问题。我建议你使用Visual Studio Community 2015.它是免费的,并提供广泛的功能。如果要重命名方法,请执行以下操作:
右键单击方法名称。
在上下文菜单中选择“重命名”
输入您想要的名称。
按Enter键
你会神奇地看到,所有对该方法的引用都改变了它们的名字!
所以你不需要将整个递归方法转换成循环或其他东西。你只需要使用正确的编辑器!
答案 3 :(得分:1)
您可以像这样创建扩展程序
public static void RecursivelyCall(this object thisObject, object [] param, [System.Runtime.CompilerServices.CallerMemberName] string methodName = "")
{
Type thisType = thisObject.GetType();
MethodInfo theMethod = thisType.GetMethod(methodName);
theMethod.Invoke(thisObject, param);
}
public static void RecursivelyCall(this object thisObject, object param, [System.Runtime.CompilerServices.CallerMemberName] string methodName = "")
{
Type thisType = thisObject.GetType();
MethodInfo theMethod = thisType.GetMethod(methodName);
theMethod.Invoke(thisObject, new object[] {param});
}
所以你可以用它来进行递归调用
private void Rec(string a)
{
this.RecursivelyCall(a);
}
但是,说实话,我不认为这是个好主意,因为
功能免疫未来的变化
不值得丢失代码可读性。
答案 4 :(得分:0)
自我引用(可能是通过反射)和递归看起来很长,当一个循环就足够了:
void SelfRef(string _Input){
while(true)
{
if (_Input == "route1"){
_Input = "route2"
continue;
}else if (_Input == "route2"){
//route2 ends
break;
}
//break?
}
}
答案 5 :(得分:0)
C#中没有构造来引用您所使用的方法并使用不同的参数调用它。您可以检查调用堆栈以找到方法 name 并使用反射来调用它,但它似乎毫无意义。
您将“免疫”的唯一类型的错误是重命名方法。在这种情况下,构建将失败,您很快就会发现出现问题。
答案 6 :(得分:0)
可以使用MethodBase.GetCurrentMethod()进行反射,这是我所知道的最快方式。当然比使用Stacktraces更快。
您可以按如下方式更改代码:
void SelfRef(string _Input){
if (_Input == "route1"){
//route1 calls route 2
MethodBase.GetCurrentMethod().Invoke(this,new []{"route2"}); //call self
}else if (_Input == "route2"){
//route2 ends
}
}
不要忘记using System.Reflection
名称空间。
答案 7 :(得分:0)
您正在使用递归,而不是自我引用
调用自身的函数(方法)被称为递归函数,这个概念称为递归。你本质上拥有的是一个名为SelfRef
的递归函数,它将一个字符串作为参数。如果参数等于"route1"
这是一个字符串,它会自行调用。
方法引用将方法传递给另一个方法
方法引用(在其他语言中调用)在C#中称为委托,用于将函数本身传递给另一个函数。这主要用于实现回调,即事件处理程序。例如,您可能会在事件中看到此代码。
public class DelegateExample
{
public delegate void MyDelegate();
public void PrintMessage(MyDelegate d)
{
d();
}
public void PrintHello()
{
Console.WriteLine("Hello.");
}
public void PrintWorld()
{
Console.WriteLine("World.");
}
public static void Main(string[] args)
{
PrintDelegate(new MyDelegate(PrintHello));
PrintDelegate(new MyDelegate(PrintWorld));
}
}
在那里,您看到,您正在将一个函数作为代理传递。
如果您知道哪些路线已经可用,请使用枚举
绝不使用字符串在对象之间进行通信或使用程序,只使用它们与用户进行交互。在编写程序时最好的选择(如果路由是预先知道的),则使用枚举来实现此目的。
答案 8 :(得分:0)
按名称调用函数不会导致代码维护问题。
当有人重命名时,所有现代开发环境(例如Visual Studio)都会自动更新该功能名称的每次使用。
如果您希望使该功能免受未来更改的影响,请保留源代码。