Самый простой пример использования закрытий находится в чем-то названном приправлением карри. В основном давайте предположим, что у нас есть функция f()
, который, когда названо с двумя аргументами a
и b
, добавляет их вместе. Так, в Python мы имеем:
def f(a, b):
return a + b
, Но скажем, ради аргумента, который мы только хотим назвать f()
с одним аргументом за один раз. Так, вместо f(2, 3)
, мы хотим f(2)(3)
. Это может быть сделано как так:
def f(a):
def g(b): # Function-within-a-function
return a + b # The value of a is present in the scope of g()
return g # f() returns a one-argument function g()
Теперь, когда мы звоним f(2)
, мы получаем новую функцию, g()
; эта новая функция несет с ним переменные от объем из [1 111], и таким образом, это сказано [1 120] близкий [более чем 1 120] те переменные, следовательно термин закрытие. К тому, когда мы звоним g(3)
, переменная a
(который связывается определением f
), получают доступ [1 115], возвращаясь 2 + 3 => 5
Это полезно в нескольких сценариях. Например, если бы у меня была функция, которая приняла большое количество аргументов, но только несколько из них были полезны для меня, я мог записать родовую функцию как так:
def many_arguments(a, b, c, d, e, f, g, h, i):
return # SOMETHING
def curry(function, **curry_args):
# call is a closure which closes over the environment of curry.
def call(*call_args):
# Call the function with both the curry args and the call args, returning
# the result.
return function(*call_args, **curry_args)
# Return the closure.
return call
useful_function = curry(many_arguments, a=1, b=2, c=3, d=4, e=5, f=6)
useful_function
теперь функция, для которой только нужны 3 аргумента, вместо 9. Я избегаю необходимости повторять меня, и также создал универсальный решение; если я пишу другую функцию много-аргумента, я могу использовать curry
инструмент снова.
Вы можете использовать что-то вроде этого:
class B {
private MainClass instance;
public B(MainClass instance)
{
this.instance = instance;
}
List SubSetList;
public void AddNewItem(A NewItem) {
Check MasterListHere ????
}
}
В C # фактически нет неявной ссылки на экземпляр включающего класса, поэтому вам необходимо передать такую ссылку, и типичный способ сделать это - через конструктор вложенного класса.
Согласно вашему определению, экземпляры класса B
могут обращаться к закрытым методам и статическим полям класса MainClass
.
Независимо от того, вкладываете ли вы класс B в класс A, любой данный экземпляр A все равно должен знать об экземпляре B, которым он удерживается. Таким образом, вы можете инициализировать A ссылкой на B и сохранить его в поле. Скорее всего, это включает его отключение.
Это может сработать для вас:
public void AddNewItem(A newItem, Func<A, bool> checkForItemInMasterList)
{
if (checkForItemInMasterList.Invoke(newItem)
SubList.Add(newItem);
}
Тогда у вас будет что-то в вашем MainClass, чтобы использовать такой метод:
public void AddItem(A newItem)
{
new B().AddNewItem(newItem, x => MasterList.Contains(x));
}
To резюмируя, это может выглядеть примерно так:
class MainClass {
class A { Whatever }
class B {
List<A> SubSetList;
public void AddNewItem(A newItem, Func<A, bool> checkForItemInMasterList)
{
if (checkForItemInMasterList.Invoke(newItem)
SubList.Add(newItem);
}
}
//I don't know how you're adding items to instances of B.
//This is purely speculative.
public void AddItem(A newItem)
{
new B().AddNewItem(newItem, x => MasterList.Contains(x));
}
List<A> MasterList;
}
Да, но вам понадобится ссылка на экземпляр MainClass внутри вашего экземпляра B.
Вы думали о том, чтобы немного переделать свои классы? Вместо того, чтобы иметь метод AddNewItem в B, вы могли бы иметь его в MainClass. Таким образом было бы легко проверить MasterList из MainClass.