C#自参考a方法
我是否可以在不使用方法名称的情况下从方法中进行自引用(出于代码维护原因,这可能会导致将来的错误) 我不想再写“SelfRef”一词,使函数不受未来更改的影响?当循环足够时,自引用(可能通过反射)和递归似乎相当冗长:C#自参考a方法,c#,C#,我是否可以在不使用方法名称的情况下从方法中进行自引用(出于代码维护原因,这可能会导致将来的错误) 我不想再写“SelfRef”一词,使函数不受未来更改的影响?当循环足够时,自引用(可能通过反射)和递归似乎相当冗长: void SelfRef(string _Input){ while(true) { if (_Input == "route1"){ _Input = "route2" continue;
void SelfRef(string _Input){
while(true)
{
if (_Input == "route1"){
_Input = "route2"
continue;
}else if (_Input == "route2"){
//route2 ends
break;
}
//break?
}
}
您可以像这样创建扩展
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);
}
但是,老实说,我认为这不是一个好主意,因为
不受未来变化影响的功能
不值得丢失代码可读性。是的,有可能:
void Foo(int bar)
{
Console.WriteLine(bar);
if(bar < 10)
MethodBase.GetCurrentMethod().Invoke(this, new object[] {++bar});
else
Console.WriteLine("Finished");
}
void Foo(整型条)
{
控制台写入线(bar);
如果(巴<10)
MethodBase.GetCurrentMethod().Invoke(这个新对象[]{++bar});
其他的
控制台。写入线(“完成”);
}
但是请永远不要使用这样的代码(很难看,很慢,很难理解,如果方法是内联的,它将不起作用)
因为您可能使用像VisualStudio这样的IDE,所以重命名方法永远不会成为问题;即使手动重命名该方法,也可能会遇到编译时错误 在C#中没有引用您所在的方法并使用不同参数调用它的构造。您可以检查调用堆栈以找到方法名并使用反射来调用它,但这似乎毫无意义
您“免疫”的唯一错误类型是重命名方法。在这种情况下,构建将失败,并且您将很快得到某个错误的指示 使用反射是可能的,这是我所知道的最快的方法。当然比使用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
}
}
不要忘记
使用System.Reflection
名称空间。现在让我们明确“自引用”的技术术语是递归。让我们开始研究这个问题
您希望编写递归方法,但由于可维护性原因,不希望“提及”方法名称。当我看到这个时,我想,“你在用什么编辑器?”。可维护性原因?你的意思是当你更改方法的名称时,代码会中断
使用IDE可以很容易地解决这些问题。我建议您使用Visual Studio Community 2015。它是免费的,并提供了广泛的功能。如果要重命名方法,请执行以下操作:
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));
}
}
您可以看到,您正在以委托的形式传递一个函数
如果您知道哪些路由已经可用,请使用枚举
切勿将字符串用于对象之间的通信或与程序的交互,仅用于与用户的交互。在编写程序时选择最佳匹配(如果路由是已知的),然后为此使用枚举
我不想再写“SelfRef”这个词,让函数不受未来变化的影响
正如其他人所说,如果您计划重命名一个方法,您应该简单地使用重命名工具
但是,创建一个不引用函数名的递归函数是一个有趣的挑战。以下是一种方法:
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
});
委托动作递归(递归r);
静态动作匿名递归(Func f)
{
递归rec=r=>a=>{f(r(r))(a);};
返回rec(rec);
}
Action SelfRef=匿名递归(
f=>
输入=>
{
如果(输入=“路由1”)
f(“路由2”);
//等等
});
注意字段SelfRef
在其主体中没有引用SelfRef
,但是递归非常简单;您只需在f
上递归,而不是SelfRef
然而,我要告诉大家的是,这段代码比简单地编写一个简单的递归方法要难理解和维护得多。按名称调用函数不会导致代码维护问题 所有现代开发环境(如Visual Studio)都会在有人重命名该函数时自动更新该函数名称的每次使用
如果要使函数不受未来更改的影响,请将源代码保存在自己的范围内。“不受未来更改的影响”是否要生成递归函数?我不认为有任何其他的方法可以做到这一点,你也许可以通过反射和堆栈跟踪一起破解一些东西。但这只是一个可能的练习,而不是实际的练习。你到底想达到什么目的?如果您的方法以测试参数的
If
开始,那么实际上在一个方法中有两个独立的功能部分,所以将它们重构为两个方法。@roryap:“如果您有开发人员正在逐个手动重命名符号,那么这是一个不同的问题。”
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
});