Захваченная переменная проблема создания - PullRequest
1 голос
/ 10 июня 2009

Я сейчас размышляю над идеей, которую не могу понять.

Проблема заключается в том, что я хочу использовать одну лямбда-функцию для создания экземпляра захваченной переменной, а другую лямбду - для доступа к свойству этой переменной.

Поскольку создание экземпляров происходит внутри лямбды, переменная фактически не создается, когда я хочу использовать ее во второй лямбде ... это своего рода проблема курицы и яйца.

Я знаю, что переменная будет инстанцирована, когда она будет использоваться во второй лямбде, но компилятор - нет.

Может ли моя идея сработать? Вот фактический код:

class Program
{
    static void Main(string[] args)
    {
        SqlCommand cmd;

        using (new DisposableComposite(
            () => cmd = new SqlCommand(),
            () => cmd.Connection)) // <- compiler error - variable not instantiated
        {
            // code
        }
    }
}

class DisposableComposite : IDisposable
{
    private List<IDisposable> _disposables = new List<IDisposable>();

    public DisposableComposite(params Func<IDisposable>[] disposableFuncs)
    {
        // ensure the code is actually executed
        foreach (var func in disposableFuncs)
        {
            IDisposable obj = func.Invoke();
            _disposables.Add(obj);
        }
    }

    public void Dispose()
    {
        foreach (var disposable in _disposables)
        {
            disposable.Dispose();
        }
    }
}

Ответы [ 3 ]

5 голосов
/ 10 июня 2009

Вы имеете в виду просто добавление:

SqlCommand cmd = null;

(который решает проблему "определенного назначения"; определенно определенно назначен ... ноль ;-p Затем мы обновляем значение перед его использованием).

IMO, однако, вы бы лучше справились с вложенными using операторами ... и неясно (из кода), откуда будет происходить фактическое соединение ...

using(var conn = new SqlConnection(...))
using(var cmd = conn.CreateCommand()) {
    // ...
}
2 голосов
/ 10 июня 2009

Этого можно избежать, только установив cmd в null перед использованием блока:

    SqlCommand cmd=null;

    using (new DisposableComposite(
        () => cmd = new SqlCommand(),
        () => cmd.Connection)) // <- compiler error - variable not instantiated
    {
        // code
    }
0 голосов
/ 10 июня 2009

Согласитесь с Марком, что это не совсем правильно.

Другим вариантом будет определение нового объекта типа Context, который при Dispose удаляет все объекты, которые он предоставляет.

Например.

using (var ctx = GetContext()) {
   var cmd = ctx.CreateCommand();
   cmd.Connection = ctx.CreateConnection();
}
// cmd is Disposed 
// cmd.Connection is Disposed 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...