执行所需的函数调用

jan*_*jan 9 c# garbage-collection dispose destructor

我在C#中有一个"Status"类,使用如下:

Status MyFunction()
{
   if(...) // something bad
     return new Status(false, "Something went wrong")
   else
     return new Status(true, "OK");
}
Run Code Online (Sandbox Code Playgroud)

你明白了.MyFunction的所有调用者都应检查返回的状态:

Status myStatus = MyFunction();
if ( ! myStatus.IsOK() )
   // handle it, show a message,...
Run Code Online (Sandbox Code Playgroud)

然而,懒惰的呼叫者可以忽略状态.

MyFunction(); // call function and ignore returned Status
Run Code Online (Sandbox Code Playgroud)

要么

{
  Status myStatus = MyFunction(); 
} // lose all references to myStatus, without calling IsOK() on it
Run Code Online (Sandbox Code Playgroud)

有可能使这不可能吗?例如抛出异常

一般来说:是否可以编写一个C#类,您必须在其上调用某个函数?

在Status类的C++版本中,我可以在析构函数中对某些私有bool bIsChecked编写测试,并在有人不检查此实例时响铃.

C#中的等价选项是什么?我在某处读到"你不想在你的C#类中使用析构函数"

IDisposable接口的Dispose方法是一个选项吗?

在这种情况下,没有非托管资源可供免费使用.此外,GC 不会确定何时处置该对象.当它最终被处置时,是否仍然可以知道忽略该特定Status实例的位置和时间?"using"关键字确实有帮助,但同样,懒惰的调用者不需要它.

Ian*_*son 10

我知道这不会直接回答你的问题,但是如果你的功能中出现"出问题"(意外情况),我认为你应该抛出异常而不是使用状态返回码.

然后将其留给调用者来捕获并处理此异常(如果可以),或者如果调用者无法处理该情况则允许它传播.

如果这是合适的,抛出的异常可以是自定义类型.

对于预期的替代结果,我同意@Jon Limjap的建议.我喜欢bool返回类型,并在方法名称前加上"Try",a la:

bool TryMyFunction(out Status status)
{
}
Run Code Online (Sandbox Code Playgroud)


Jon*_*jap 7

如果你真的想要求用户检索MyFunction的结果,你可能想要取消它而使用out或ref变量,例如,

void MyFunction(out Status status)
{
}
Run Code Online (Sandbox Code Playgroud)

它可能看起来很丑陋,但至少它确保将一个变量传递给函数,该函数将获取您需要它获取的结果.

@Ian,

异常的问题在于,如果某些事情经常发生,您可能会为异常花费太多系统资源.真正的异常应该用于异常错误,而不是完全预期的消息.


Wee*_*ble 2

我相当确定你无法从方法的返回值中获得你想要的效果。C# 无法完成 C++ 可以做的一些事情。然而,获得类似效果的一种有点丑陋的方法如下:

using System;

public class Example
{
    public class Toy
    {
        private bool inCupboard = false;
        public void Play() { Console.WriteLine("Playing."); }
        public void PutAway() { inCupboard = true; }
        public bool IsInCupboard { get { return inCupboard; } }
    }

    public delegate void ToyUseCallback(Toy toy);

    public class Parent
    {
        public static void RequestToy(ToyUseCallback callback)
        {
            Toy toy = new Toy();
            callback(toy);
            if (!toy.IsInCupboard)
            {
                throw new Exception("You didn't put your toy in the cupboard!");
            }
        }
    }

    public class Child
    {
        public static void Play()
        {
            Parent.RequestToy(delegate(Toy toy)
            {
                toy.Play();
                // Oops! Forgot to put the toy away!
            });
        }
    }

    public static void Main()
    {
        Child.Play();
        Console.ReadLine();
    }
}
Run Code Online (Sandbox Code Playgroud)

在这个非常简单的示例中,您可以通过调用 Parent.RequestToy并向其传递一个 delegate 来获取 Toy 的实例。该方法不返回玩具,而是立即使用玩具调用委托,该委托必须在返回之前调用 PutAway,否则 RequestToy 方法将引发异常。我没有宣称使用这种技术是否明智——事实上,在所有“出了问题”的例子中,例外几乎肯定是更好的选择——但我认为它会尽可能接近你最初的要求。