2012-05-22 4 views
2

C# новичок здесь.Комплексное использование делегатов

В одном из моих классов (класс сущностей, чтобы быть точным), у меня есть делегат, который принимает в Сущности и другого соответствующего класса:

public delegate void FiringFunc(Entity e, BulletFactory fact) 

и петлей в классе сущностей, которая называет это функционировать каждый кадр (если его определить):

FiringFunc firingFunc = null; //defined later 
if(firingFunc) 
    firingFunc(this, someBulletFactory);  

как можно было бы, вероятно, сказать, что это делегат, который служит в качестве функции пули стрельбы (вы бы кодировать что-то вроде таймера для пули, углы, чтобы стрелять , и т.д). Однако мне пришла в голову мысль: что, если я хочу, чтобы у пули была небольшая разница, но она все равно останется такой же (что-то вроде немного медленнее, немного другого цвета, в другом направлении и т. Д.). Мне нужно было бы создать еще одну функцию, чтобы служить делегатом - мне это показалось неправильным.

Вот пример того, что создание и настройка делегата будет выглядеть следующим образом:

Entity e = new Entity(...) 
e.firingFunc = FiringFunctions.SomeFiringFunctionName; 

Есть ли способ, которым я мог бы добавить параметры к этому? Было бы замечательно, если бы я мог сделать что-то похожее на следующее:

e.firingFunc = FiringFunctions.SomeFiringFunctionName(someChange1, someChange2); 

ответ

3

Попробуйте

e.firingFunc = 
    (Entity e, BulletFactory fact) => 
     FiringFunctions.SomeFiringFunctionName(e, fact, "foo", 5); 

Это создает новую анонимную функцию (лямбда), которая вызывает FiringFunctions.SomeFiringFunctionName с включенными параметрами.

Это предполагает, что FiringFunctions.SomeFiringFunctionName определяется как:

public void SomeFiringFunctionName(Entity e, BulletFactory fact, String someString, Int32 someInt) { 
    //... do whatever here 
} 
+2

В пользу читателей эта техника (аргументы функции предварительной подачи) называется «currying», и этот пример - это абсолютно правильный способ сделать это на C#. – cdhowie

+0

Очень интересно - я рассматривал функции лямбда как решение моей проблемы, но не знал, как подойти к ней. Это эквивалентно делать что-то вроде: 'общественного делегата недействительного FiringFunc (Entity е, BulletFactory факта, объект пар [] extraStuff);' и поставляет ' "Foo" и' 5' как 'extraStuff'? –

+0

@ LiChE: да, кроме представленного выше случая каррирования, вам не пришлось бы маршалировать все параметры в контейнер 'object []'. У вас может быть безопасность типа времени компиляции и intellisense при вызове соответствующей функции (которая может принимать разные типы/количество параметров) – mellamokb

1

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

public interface IFiringActionProvider 
{ 
    public void Fire(Entity e, BulletFactory fact); 
} 

Затем в том же Entity класса:

IFiringActionProvider firingFunc = null; //defined later 
if (firingFunc != null) 
    firingFunc.Fire(this, someBulletFactory); 

Вы можете создавать собственные экземпляры в любой форме вы хотели бы, такие как:

public class CustomColorFiringActionProvider : IFiringActionProvider 
{ 
    private Color color; 
    public CustomColorFiringActionProvider(Color c) { this.color = c; } 
    public void Fire(Entity e, BulletFactory fact) 
    { 
     // do something, using color 
    } 
} 

Просто добавить еще один подобный подход (не обязательно лучше).