Пользовательский класс работает как оператор использования с фигурными скобками - PullRequest
0 голосов
/ 26 сентября 2018

Можно ли создать класс или оператор, который работал бы как , используя делает?

Пример:

using (IDataReader reader = cmd.ExecuteReader())
{
  while (reader.Read())
  {
    count++;
  }
}

Часто мы используем using заявление о том, что не нужно обрабатывать почтовые операции вручную, например dispose и т. д.

Я имею в виду несколько случаев использования этого механизма.
Но я не могу понять, как этого добиться.

Пример реальной реализации:

  MyClass mc = new MyClass();
  MyClass sub = mc.GoDown();
  //Do things on sub
  sub.GoUp();

То, что я хотел бы, чтобы это было:

  MyClass mc = new MyClass();
  mc.GoDown {
    //Do things on sub
  } // GoUp

Я знаю, что мог бы использовать try {} finally {}.Мне просто любопытно, есть ли способ сделать то, что делает using.

Редактировать: я знаю о реализации IDispose.Мне просто интересно, можем ли мы сделать то, что using делает без using.

Редактировать # 2: Улучшен пример.

Ответы [ 3 ]

0 голосов
/ 26 сентября 2018

Наиболее близкой конструкцией к тому, что вы мне предложили, будет метод, который принимает объект и Func или Action в качестве аргумента, и если объект имеет определенный тип - например, реализует интерфейс, затем выполняетtask.

Давайте начнем с интерфейса:

public interface IMyWrapper
{
    void Do();
}

Для простоты я создал один пример для Action, который не принимает никаких аргументов:

public class MyWrapper
{
    public static void MyWrapperMethod(IMyWrapper wrapped, Action doStuff)
    {
        try
        {
            doStuff();
        }
        finally
        {
            wrapped.Do();
        }
    }

    public static void MyWrapperMethod(object notWrapped, Action doStuff)
    {
        doStuff();
    }
}

IFВы передаете объект, который реализует интерфейс IMyWrapper, он будет запускать метод Do() интерфейса IMyWrapper после выполнения действия, указанного в действии doStuff.В противном случае он просто запустит doStuff.

, чтобы запустить его так:

MyWrapper.MyWrapperMethod(new object(), () =>
{
    Console.WriteLine("Do stuff");
});

Это будет писать только «Делать вещи».

Давайте сейчассоздайте класс, который влияет на интерфейс:

public class MyWrappedClass : IMyWrapper
{
    public void Do()
    {
        Console.WriteLine("I implement the wrapper.");
    }
}

и используйте его в MyWrapperMethod:

var myWrappedClass = new MyWrappedClass();
MyWrapper.MyWrapperMethod(myWrappedClass, () =>
{
    Console.WriteLine("Do stuff");
});

Это будет печатать «Делать вещи» и «Я реализую оболочку».Это б / к, MyWrapperMethod выполнит для нас метод Do.

Это самое близкое к тому, что using я мог придумать.

0 голосов
/ 26 сентября 2018

Вот как можно заставить пример работать, передав Action<MyClass> в GoDown, и GoDown будет обрабатывать вызов GoUp на sub.

public class MyClass
{
    public MyClass GoDown(Action<MyClass> doStuff)
    {
        var sub = new MyClass();
        //Whatever GoDown did to create a MyClass goes here

        try
        {
            doStuff(sub);
        }
        finally
        {
            sub.GoUp();
        }
    }
}

Затем вызовите еговот так.

MyClass mc = new MyClass();
mc.GoDown(sub =>
{
    //Do things on sub
});

И GoUp будет вызываться на sub, даже если в делегате, который вы передаете, есть исключение.

0 голосов
/ 26 сентября 2018

Вашему классу просто необходимо реализовать IDisposable для поддержки использования в блоке using:

public class MyClass : IDisposable
{
    public void Dispose()
    {
        // Do your cleanup
    }
}

Тогда вы можете использовать:

using (var instance = new MyClass())
{

}

Do read РеализацияУтилизируйте метод в Microsoft Docs.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...