gonzalo123/using

PHP中C#使用语句的实现

dev-master / 1.0.x-dev 2015-06-21 11:19 UTC

This package is not auto-updated.

Last update: 2024-09-14 14:46:39 UTC


README

在PHP中实现C#的"using"语句

Build Status Latest Stable Version

用法

using(new File(__DIR__ . "/file.txt", 'w'), function (File $file) {
        $file->write("Hello\n");
        $file->write("Hello\n");
        $file->write("Hello\n");
    });

问题

想象这个类

class File
{
    private $resource;

    public function __construct($filename, $mode)
    {
        $this->resource = fopen($filename, $mode);
    }

    public function write($string)
    {
        fwrite($this->resource, $string);
    }

    public function close()
    {
        fclose($this->resource);
    }
}

我们可以使用这个类

$file = new File(__DIR__ . "/file.txt", 'w');
$file->write("Hello\n");
// ...
// some other things
// ...
$file->write("Hello\n");
$file->close();

如果在"some other things"中发生异常会发生什么?简单:close()函数没有被调用。

解决方案

我们可以用try - catch来解决问题

try {
    $file->write("Hello\n");
    // ...
    // some other things
    // ...
    $file->write("Hello\n");
    $file->close();
} catch (\Exception $e) {
    $file->close();
}

或者在PHP5.5中使用"finally"关键字

try {
    $file->write("Hello\n");
    // ...
    // some other things
    // ...
    $file->write("Hello\n");
} catch (\Exception $e) {
} finally {
    $file->close();
}

更好的解决方案

C#有"using"语句以智能方式解决这个问题。

http://msdn.microsoft.com/en-us//library/yh598w02(v=vs.90).aspx

我们将在PHP中实现类似的功能。

首先,我们将G\IDisposable接口添加到我们的File类中

namespace G;

interface IDisposable
{
    public function dispose();
}

现在我们的File类看起来像这样

class File implements IDisposable
{
    private $resource;

    public function __construct($filename, $mode)
    {
        $this->resource = fopen($filename, $mode);
    }

    public function write($string)
    {
        fwrite($this->resource, $string);
    }

    public function close()
    {
        fclose($this->resource);
    }

    public function dispose()
    {
        $this->close();
    }
}

然后我们可以在PHP中使用我们的"using"函数

using(new File(__DIR__ . "/file.txt", 'w'), function (File $file) {
        $file->write("Hello\n");
        $file->write("Hello\n");
        $file->write("Hello\n");
    });

正如我们所见,我们可以忘记关闭()我们的文件实例。"using"会为我们做这件事,即使内部抛出一个异常。

我们还可以使用一个实现IDisposable接口的实例数组(当然)

using([new Bar, new Foo], function (Bar $bar, Foo $foo) {
        echo $bar->hello("Gonzalo");
        echo $foo->hello("Gonzalo");
    });