C# делегирует использование реального мира [дубликат]

На практике это редко имеет значение. Это - прежде всего, вопрос персонального предпочтения.

Это очень популярно для помещения открытых методов сначала, якобы так, чтобы пользователи класса были в состоянии найти их более легко. Но заголовки никогда не должны быть Вашим основным источником документации, таким образом основывая "лучшие практики" вокруг идеи, что пользователи будут смотреть на Ваши заголовки, кажется, промахивается для меня.

Это более вероятно для людей быть в Ваших заголовках, если они изменение класс, в этом случае они должны забота о закрытом интерфейсе.

, Какой бы ни Вы выбираете, сделайте свои заголовки чистыми и легкими читать. Способность легко найти безотносительно информации, которую я, оказывается, ищу, являюсь ли я пользователем класса или специалистом по обслуживанию класса, является самой важной вещью.

6
задан sleath 15 October 2009 в 15:50
поделиться

11 ответов

Предполагая, что вы не говорите о событиях - конечно, вы можете программировать вокруг этого. Дело в том, чтобы сделать его лучше и чище .

protected void Sort()
{
    foreach (string key in _dBase.Keys)
    {
      Array.Sort<Pair<string, Dictionary<string, T>>>(_dBase[key], 
            new Comparison<Pair<string, Dictionary<string, T>>>(
        delegate(Pair<string, Dictionary<string, T>> a, Pair<string, Dictionary<string, T>> b)
        {
            if (a == null && b != null)
                return 1;
            else if (a != null && b == null)
                return -1;
            else if (a == null && b == null)
                return 0;
            else
                return a.First.CompareTo(b.First);
        }));
    }
}

Могу ли я сделать это без встроенного делегата? Конечно. Будет ли у меня в классе гибкий частный метод, который будет использоваться только для этого одного экземпляра? Ага.

Изменить: Как упоминалось в комментариях, вы можете упростить:

Array.Sort<Pair<string, Dictionary<string, T>>>(_dBase[key], 
   new Comparison<Pair<string, Dictionary<string, T>>>(
   delegate(Pair<string, Dictionary<string, T>> a, Pair<string, Dictionary<string, T>> b)
   {

до

Array.Sort<Pair<string, Dictionary<string, T>>>(_dBase[key], (a,b) =>
   {
3
ответ дан 8 December 2019 в 05:22
поделиться

Использование в реальном мире:

  1. Предположим, у вас есть простой пользовательский элемент управления под названием Checker , который состоит всего из двух флажков - chkA и chkB.
  2. В пользовательском элементе управления вы можете управлять событиями проверки / снятия отметки, реализуя соответствующие события для chkA и ChkB

3. Теперь в новой форме Win, когда вы перетаскиваете Checker . ..и ваша цель - убедиться, что при нажатии chkA вы должны изменить цвет фона метки ... lblColorPicker.

Имейте в виду, что lblColorPicker - это элемент управления, который существует в форме и не привязан напрямую к Шашка .

Как вы этого добьетесь?

Ответ:

  1. Во-первых, вы должны создать новое событие для вашего пользовательского элемента управления Checker .
  2. Чтобы создать это новое событие, сначала нужно быть для создания делегата в вашем пользовательском элементе управления, а затем использовать этот делегат в качестве определяющего типа для нового события, которое вы пишете.
  3. И затем это событие должно быть сопоставлено с событием chkA ... в вашем пользовательском элементе управления.

Таким образом, вы можете управлять chkA ... через новое событие из любой новой формы, ссылаясь на событие ... через только что написанный вами делегат.

Итак, много для использования в реальном мире!

Эта цель НЕ МОЖЕТ быть достигнута без записи делегата.

Сообщите мне, если вы думаете иначе ... или если вам нужно больше разработка.

3
ответ дан 8 December 2019 в 05:22
поделиться

Допустим, у вас есть консольное приложение, которое реагирует на различные нажатия клавиш:

            Action a = () => {/* Do Stuff*/};
            Action b = () => {/* Do Stuff*/};
            Action c = () => {/* Do Stuff*/};
            Action d = () => {/* Do Stuff*/};
            Action e = () => {/* Do Stuff*/};
            Action f = () => {/* Do Stuff*/};
            Action g = () => {/* Do Stuff*/};
            Action h = () => {/* Do Stuff*/};
            Action i = () => {/* Do Stuff*/};
            Action j = () => {/* Do Stuff*/};

            List<Action> actions = new List<Action>() {a,b,c,d,e,f,g,h,i,j};

            string line;

            while((line = Console.ReadKey().KeyChar) != 'q')
            {
                if(line.isBetween_0_and_9())
                {
                    actions[line.ParseInt()]();
                }
            }

Очевидно, вы можете просто использовать кучу If, но это не только проще, но и почти наверняка более четкое / читаемое.

1
ответ дан 8 December 2019 в 05:22
поделиться

Оператор переключения Perl: given / when

Perl, начиная с версии 5.10 и выше, имеет фантастический встроенный оператор переключения, называемый [ given ]. Это примерно эквивалентно оператору switch в C, но гораздо более универсально. Чтобы включить эту функцию, вам нужно добавить строку вверху вашего скрипта:

use 5.010;

Это включает все функции perl 5.10, включая переключатель (и , скажем, , который работает как print ], но автоматически добавляет "\ n" в конце.) Вы можете использовать это так:

my $foo = get_foo();
my $nothing = 0;
given($foo) {
    when (undef)  { say "got an undefined value!"; }
    when ([1,3,5,6,8]) { say "was 1, 3, 5, 6, or 8"; }
    when (/^abc/) { say "was a string starting with abc"; }
    when ($_ == 4) { say "It was 4!!!"; }
    when ($_ > 100) { say "Greater than 100"; }
    default { $nothing = 1; }
}

Переменная, переданная в given, автоматически помещается в $ _ внутри данного кода, что позволяет сравнивать против этого. Затем конструкция when выполняет интеллектуальное сопоставление с $ _. Итак, в вашем случае Мне нужно перейти к другому методу, чтобы увидеть код, который принадлежит вашему методу:

Пример Winforms

class MyForm:Form{
//...
protected override void OnLoad(EventArg e){
   this.Cursor=Cursors.Wait();
   this.Enabled=false; 

   // do a long running DB operation without blocking the UI Thread
   ThreadPool.QueueUserWorkItem(state=>{

     DoLongDBOperation();

     // re enable the form
     BeginInvoke(new Action(()=>{ this.Cursor=Cursors.Default;this.Enabled=true;}));

   });
}
2
ответ дан 8 December 2019 в 05:22
поделиться

Об этом никто не упоминал, но если вы используете LINQ с Lambda, вы все время используете анонимные методы. Которые технически все еще являются делегатами .

Допустим, у вас есть класс с именем Person

class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

, и вы хотели реализовать метод поиска, в котором вы могли бы найти человека на основе его имени

public Person Where(List<Person> list, string firstName)
{
   //find the string
   foreach(Person item in list)
      if(item.FirstName.Equals(firstName))
        return item;
}

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

К счастью, LINQ предоставляет метод расширения под названием Where , который вам нужен передать делегат , который вы можете создать на лету с помощью анонимных методов.

например

string searchString = "Stan";
list.Where( person => person.FirstName.Equals(searchString));

, но если вы хотите перейти на поиск по фамилии, вы просто сделаете это

string searchString = "R";
list.Where( person => person.LastName.Equals(searchString));

] Этот пример может оказаться не тем, что вы искали,

3
ответ дан 8 December 2019 в 05:22
поделиться

Когда бы вы ни использовали шаблон стратегии или шаблон наблюдателя, делегаты значительно упрощают вашу работу, чем использование интерфейсов.

4
ответ дан 8 December 2019 в 05:22
поделиться

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

1
ответ дан 8 December 2019 в 05:22
поделиться

Я думаю, вы имеете в виду определение пользовательских делегатов?

] EventHandler минимизировал потребность в пользовательских определениях делегатов, но они по-прежнему полезны, если вы хотите добавить дополнительные параметры к сигнатуре метода.

1
ответ дан 8 December 2019 в 05:22
поделиться

Whenever you need to modify or change any properties of a winForms control, you need to use a delegate to pass control back to the thread the control was created on... to name just one of many examples.

1
ответ дан 8 December 2019 в 05:22
поделиться

If you imagine C# without delegates, you would commonly encounter situations where you have classes or interfaces with one method. The name of that method is redundant. e.g.

public interface IGetMail
{
    Mail JustGetTheMail();
}

The interface is all about that one method. A reference to an object of that type is really no more than a reference to a single callable method. The calling code:

Mail m = getMail.JustGetTheMail();

could be abreviated to:

Mail m = getMail();

The compiler could do that as "syntactic sugar" without any ambiguity, because there's only one method you could possible call on that getMail reference.

So let's add that feature to our C# compiler. Now, when declaring these types, we could make that a little neater as well. We don't need to specify the method name when calling it, so why should we have to give the method a name in the first place?

Let's pick a standard method name, Invoke, i.e.

public interface IGetMail
{
    Mail Invoke();
}

We'll add some more syntactic sugar to allow us to write that as:

public delegate Mail GetMail();

Hey presto. We've added delegates to our C# compiler.

(Technically the CLR is also aware of delegates, and so rather than generating an interface, the C# compiler generates a special "delegate" type, which has support for asynchronous invocation, and manipulating an immutable list of delegates and treating them as a single reference; but in a basic form it could have been done with interfaces. There is a proposal to do that for Java).

We can then go further and add anonymous delegates - making them succinct to implement in a way that interfaces are not.

So to answer your question - any time where your interface has one method, it could be a delegate, and you'll be able to seriously cut down the amount of junk code you have to write.

3
ответ дан 8 December 2019 в 05:22
поделиться

Одним из примеров может быть диспетчер сообщений публикации / подписки. Вам нужно будет зарегистрировать события в диспетчере, а затем вызвать их соответствующим образом. Это позволяет вам довольно легко соединять разрозненные части вашего кода. Я не могу придумать, как это сделать без использования делегатов

1
ответ дан 8 December 2019 в 05:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: