在不设置参数的情况下抛出异常时的行为是什么?

时间:2014-02-17 09:45:08

标签: c# exception-handling out

在设置out参数的值之前抛出异常时,C#中定义的行为是什么,然后尝试访问参数?

public void DoSomething(int id, out control)
{
    try
    {
        int results = Call(Id);
        control = new CallControl(results);
    }
    catch(Exception e)
    {
      throw new Exception("Call failed", e);
    }
}

//somewhere else
DoSomething(out Control control)
{
    try
    {
       DoSomething(1, out control);
    }
    catch()
    {
    // handle exception
    }
}

// later
Control control;
DoSomething(out control)
control.Show();

编译器通常会在设置out参数之前抱怨退出该方法。这似乎超越了保护我自己。

3 个答案:

答案 0 :(得分:4)

  

在设置out参数的值之前抛出异常时,C#中定义的行为是什么,然后尝试访问参数?

你不能这样做。除非在方法调用之前明确赋值,否则变量仍然不会被明确赋值。

如果在方法调用之前明确赋值变量 ,那么它仍然会被明确分配 - 但除非方法在之前分配了值,否则抛出异常,变量的值将保持不变:

class Test
{
    static void JustThrow(out int x)
    {
        throw new Exception();
    }

    static void Main()
    {
        int y = 10;
        try
        {
            JustThrow(out y);
        }
        catch
        {
            // Ignore
        }
        Console.WriteLine(y); // Still prints 10
    }
}

答案 1 :(得分:1)

没关系。如果DoSomething抛出,则control.Show()未执行。

答案 2 :(得分:0)

无论如何,你无法超越编译器,因为它知道控制流何时可以绕过初始化。

考虑这段代码,它类似于你提出的代码:

using System;

namespace Demo
{
    internal class Program
    {
        private void run()
        {
            int a;

            try
            {
                DoSomething(out a);
            }

            catch {} // Evil empty catch.

            Console.WriteLine(a); // Compile error.
        }

        public void DoSomething(out int x)
        {
            test();
            x = 0;
        }

        private static void test()
        {
            throw new InvalidOperationException("X");
        }

        private static void Main()
        {
            new Program().run();
        }
    }
}

它给出了编译错误,因为你在DoSomething()附近放了一个try / catch,因此编译器认为a可能没有被初始化。

(请注意,如果您没有显式初始化它们,所有堆栈变量都会初始化为默认值,但这不会影响编译器的控制流分析。编译器关心明确的赋值,而不是CLR的默认初始化无论如何,C#标准无法保证这种初始化。)

如果将空捕获更改为抛出的捕获,则编译错误消失:

catch { throw new Exception("Test"); } // Compile error goes away.

因为现在如果发生异常,您无法访问使用a的代码。