如何实例化一个对象并将其传递给“using”块声明中的方法

时间:2016-04-14 10:41:28

标签: c# .net idisposable

我正在使用一个实现IDisposable的外部类和一​​个填充该类实例的外部方法。

我正在寻找一种巧妙的方法来将一次性对象封装在“using”语句中,但无法解决语法问题。

让我们说课程是......

class Something : IDisposable

功能是......

void PopulateSomething(Something theObject)

我能做到这一点......

Something myObject = new Something();
PopulateSomethingObject(myObject);
x = myObject.SomeNumber;
myObject.Dispose();

或者我也可以这样做......

Something myObject = new Something();
using(myObject)
{
    x = myObject.SomeNumber;
}

但上述两者都不是很好,因为在处理后我可能会愚蠢地写出像这样的东西

x = myObject.SomeNumber; // which will throw an exception

我想我能做到这一点......

using(Something myObject = new Something())
{
    PopulateSomethingObject(myObject);
    x = myObject.SomeNumber();
}

但我想相信以下内容是可能的,但我无法弄清楚语法......

using (Something myObject => PopulateSomethingObject(myObject = new Something()))
{
    x = myObject.SomeNumber();
}

我想这是一个理论问题,因为我在这里确实没有问题,但我很想知道它是否可行。即实例化对象并将其传递给“using(...){}块声明中的方法。

4 个答案:

答案 0 :(得分:1)

问题是PopulateSomething方法的签名,这会阻止您在单个表达式中创建和使用Something个对象。由于PopulateSomething的返回类型为void,因此必须将其用作语句,而不是表达式。

你编写的最后一种方法非常好:

using (Something myObject = new Something()) {
    PopulateSomethingObject(myObject);
    x = myObject.SomeNumber();
}

实际上,当在using内创建的对象在使用之前经历了一些额外的配置时,它类似于数据库连接使用的模式:

using (conn = factory.CreateConnection()) {
    // Do more things to conn before its first use.
    conn.ConnectionString = "...";
    conn.Open();
    ... // Use conn here
}

如果您想避免在PopulateSomethingObject内拨打using,请将工厂方法设为Something,如下所示:

private static Something GetAndConfigure() {
    Something res = new Something();
    PopulateSomethingObject(res);
    return res;
}

现在你可以写

using (Something myObject = GetAndConfigure()) {
    x = myObject.SomeNumber();
}

答案 1 :(得分:1)

这是你可以做的事情

private Something CreateAndPopulate()
{
    var myObject = new Something();
    PopulateSomethingObject(myObject);
    return myObject;
}

然后使用它:

using (var myObject = CreateAndPopulate())
{
    x = myObject.SomeNumber();
}

<强> UPDATE1 另一种方法是编写Something的扩展名

public static class SomethingExtension
{
    public static Something Populate(this Something someObj, Action<Something> actionToPopulate)
    {
        actionToPopulate.Invoke(someObj);
        return someObj;
    }
}

然后在一行中使用它,如:

using (var myObject = new Something().Populate(PopulateSomethingObject))
{
    x = myObject.SomeNumber();
}

<强> UPDATE2 Fianlly,一线方式可能看起来很复杂

using (var myObject = new Func<Something>(() =>
                    {
                        var myNewObject = new Something();
                        PopulateSomethingObject(myNewObject);
                        return myNewObject;
                    }).Invoke())
{
    //x = myObject.SomeNumber();
}

答案 2 :(得分:0)

{{1}}

这是USING块的正确用法。您在括号内创建实例。

如果你真的不想处理这个对象那么你就不应该首先使用USING。

答案 3 :(得分:0)

不,你应该只在using内放置对象。 而对于我的观点,这个想法并不是那么好。我看到代码的两个部分 - 第一个路径创建对象,第二个路径 - 处理它。你尝试将第一部分与第二部分混合。我认为最后一个选项的可读性低于

using(Something myObject = new Something())
{
    PopulateSomethingObject(myObject);
    x = myObject.SomeNumber();
}