【问题标题】:Trigger code after or before return返回之后或之前触发代码
【发布时间】:2014-11-05 01:47:06
【问题描述】:

如何在调用返回之前/之后执行某些部分代码。例如 return 可能在一个方法中被多次调用,因此我不希望在 return 之前复制粘贴相同的行。

我可能错了,但有些人告诉我 try 块会使代码运行缓慢,而且我的方法被调用了 1000 多次,因此即使这个任务可以用 try/finally 块完成,我也想避免它。

例子:

void method()
{
 MyObject activator = new ...
 AnotherObject something = new ...
 SomethingElse asdf = new ...
 // some other variables 
 if(..)
    // Deactivate activator, close things, confirm user exited
    // Do some post calculations
   return;
 if(..)
    // Deactivate activator, close things, confirm user exited
    // Do some post calculations
   return;
 if(..)
    // Deactivate activator, close things, confirm user exited
    // Do some post calculations
  return;
}

现在我需要在每次返回之前或之后执行相同的代码。我需要使用在方法顶部定义的变量的代码,这就是我不能外包的原因。这个怎么做?有办法吗?如有重复,我深表歉意。

【问题讨论】:

  • 使用else if 没有回报?
  • try 块非常有效,只要不抛出异常(导致堆栈跟踪缓慢)
  • 你能举一个更完整的例子来说明你想要达到的目标吗?需要调用什么代码?
  • 如果您不愿意使用try/final 块,您愿意使用goto-label 组合吗? msdn.microsoft.com/en-us/library/13940fs2.aspx
  • @judgeja 我也想过,但我无法改变这个要求。

标签: c#


【解决方案1】:

我不太清楚您要达到的目标,但根据您的帖子,您可以使用可怕的 goto 声明!

public void Test()
{
    if (...)
        goto Finish;
    if (...)
        goto Finish;
    
    Finish:
    DoSomething();  
}

根据您的更新,我肯定会考虑使用 finally 块:

void Main()
{
    try 
    {
     MyObject activator = new ...
     AnotherObject db_connection = new ...
     Proxy p = new ...
     // some other variables 
     if(..)
      return;
     if (...)
        return;
    }
    finally
    {
        // Deactivate activator, close db connection, call a webservice to confirm user exited
        // Do some post calculations
    }
}

try-finally 的效率

try-finally 模式非常有效。考虑以下代码:

try
{
    Console.WriteLine("Foo");
}
finally
{
    Console.WriteLine("Bar");
}

这将编译为以下 IL:

IL_0000:  ldstr       "Foo"
IL_0005:  call        System.Console.WriteLine
IL_000A:  leave.s     IL_0017
IL_000C:  ldstr       "Bar"
IL_0011:  call        System.Console.WriteLine
IL_0016:  endfinally  

英文是:

加载字符串“Foo”并用它调用WriteLine。我们有一个finally 语句,所以当我们调用它时,转到位置IL_0017 - 方法的结尾。加载字符串“Bar”并用它调用WriteLine。 finally 现在已经完成,所以我们可以继续到 finally 块之前定义的位置。

【讨论】:

  • 鼓励人们采取不良做法是完全错误的
  • goto 有它的位置。它只是被认为是“坏的”,因为你必须小心你所做的事情,但如果它使代码更清晰、更简洁,那就没有理由不使用它!
  • @YuvalItzchakov 我不同意。 goto 在 C# 中有它的位置和用法。不过,我不确定是不是这样。
  • @dav_i 正在尝试让事情变慢一点?
  • 当放入try{...} 时,MyObject activator 之类的实例在相应的finally{...} 中看不到。
【解决方案2】:

也许考虑一个 try-finally 构造。它用于可以引发异常的代码路径,但仍必须始终进行清理(即使在引发异常之后)。

http://msdn.microsoft.com/en-us/library/zwc8s4fz.aspx

void method() {
     MyObject activator = new ...
     AnotherObject db_connection = new ...
     Proxy p = new ...
     try{
         // some other variables 
         if(..)
            // Do some post calculations
         if(..)
            // Do some post calculations
         if(..)
            // Do some post calculations
    }
    finally{
        // Deactivate activator, close db connection, call a webservice to confirm user exited
    }
      return;
}

// 更新

我想知道如果 try/finally 的性能如此之高以至于它会破坏您的应用程序,您是否不应该重新设计您的应用程序或代码路径。您似乎在很短的时间内打开和关闭连接 1000 多次。这是连接到 1000 多个数据库,还是连接到数据库的 1000 多个用户?为什么不保持开放?您能否分享一些有关该用例的其他详细信息?

【讨论】:

【解决方案3】:

我还不清楚你在寻找什么。 但我理解的是。你想用值实例化几个对象,一旦完成,你想在你离开方法之前dispose/disconnect它们。

这就是我对控制台应用程序的尝试, 您可以在 Disposed() 方法中处理/断开您的值。

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Callmethod();
            Console.WriteLine("--------------------");
            Console.WriteLine("Disposed");
            Console.ReadKey();
        }

        private static string Callmethod()
        {
            using (MyObject obj = new MyObject())
            {
                Console.WriteLine(obj.strTest);
                Console.WriteLine("..");
                Console.WriteLine("..");
                Console.WriteLine("..");
                Console.WriteLine("..");
                return obj.strTest;
            }
        }
    }
    public class MyObject : IDisposable
    {
        public string strTest { get; set; }
        public MyObject()
        {
            strTest = "Intantiated";
        }

        public void Dispose()
        {
            Console.WriteLine("Disposing");
        }
    }
}

希望对你有帮助

【讨论】:

  • 是的。试试吧。您可以将您的代码应用到类的Dospose() 方法中
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多