C#自参考a方法

C#自参考a方法,c#,C#,我是否可以在不使用方法名称的情况下从方法中进行自引用(出于代码维护原因,这可能会导致将来的错误) 我不想再写“SelfRef”一词,使函数不受未来更改的影响?当循环足够时,自引用(可能通过反射)和递归似乎相当冗长: void SelfRef(string _Input){ while(true) { if (_Input == "route1"){ _Input = "route2" continue;

我是否可以在不使用方法名称的情况下从方法中进行自引用(出于代码维护原因,这可能会导致将来的错误)

我不想再写“SelfRef”一词,使函数不受未来更改的影响?

当循环足够时,自引用(可能通过反射)和递归似乎相当冗长:

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