C# как создать следующий метод синтаксиса (param => {params.xxx})?

В примере кода я видел следующий код:

SomeClass.Columns(columns => {
        columns.Add()
            .Text("Product")
            .Value("123");

        columns.Add()
            .Text("Amount")
            .Value("456");
})

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

Где columns - это набор объектов Column и .Text и .Value - это методы объекта Column, которые снова возвращают Object (для создания свободного синтаксиса).

columns.Add() вернет объект new Column()

Какими будут параметры в методе SomeClass.Columns (???)? Есть ли у этого синтаксиса конкретное имя, которое я могу изучить?

Спасибо.

Обновлено:

Да, в моем примере есть свободный синтаксис, но это был не мой вопрос, извините, что я не понял.

Вопрос в том, как мне сделать следующее:

SomeClass.Columns(columns => { ... })

Так как же выглядит параметр в методе Columns?

Спасибо.

Разве это не просто свободный синтаксис? ...

Stefan 10.08.2018 14:33

Думаю, вы наверняка ищете лямбда-выражения и / или делегаты

bassfader 10.08.2018 14:34

@TimSchmelter Columns - это метод, а не свойство. Спасибо

lordvlad30 10.08.2018 14:39
1
3
124
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Это называется Fluent-интерфейсом или Fluent-методом. Это работает так: все .Add(), .Text() и .Value() впоследствии возвращают тот же объект, с которым они выполняют операции, в качестве возвращаемого значения. Это то, что позволяет таким образом связывать операции. Columns просто возвращает перечислимое количество тех же самых объектов.

В этом случае Columns принимает что-то вроде Action<ColumnCollection>. То есть вы передаете ему делегат / лямбда, он обещает вызвать эту лямбду, передав в независимо от того, что будет columns, а затем в своем лямбда / делегате вы можете манипулировать коллекцией.

Кажется, это ответ, я постараюсь реализовать это в своем коде (и через несколько минут проголосуйте за этот ответ, если к тому времени он все еще будет лучшим ответом). Спасибо

lordvlad30 10.08.2018 14:38

Not Func <ColumnCollection, ColumnCollection>? передать столбцы и вернуть новую коллекцию, созданную из методов Add (), Text () и Value ()

Hyarus 10.08.2018 14:39

@Hyarus - лямбда, показанная в вопросе, явно void. Это не одна строчка и нет return. Add и т. д. Явно манипулируют каким-то изменчивым типом.

Damien_The_Unbeliever 10.08.2018 14:41

@Hyarus - конечно, сам Columns может иметь возвращаемый тип ColumnCollection, если это подходит для свободного интерфейса, но я бы подумал, что вместо этого он вернет то, что есть SomeClass.

Damien_The_Unbeliever 10.08.2018 14:43

Это функции высшего порядка. В языке C# он присутствует как классы Action и Func. Ответ на ваш вопрос и семантика метода Columns примерно так:

public ColumnCollection Columns(Func<ColumnCollection,ColumnCollection> columnCollectionFunc)
    => columnCollectionFunc(_someInternalColumnCollection);

Я не думаю, что это List<ColumnClass>, потому что Add здесь работает иначе.

Damien_The_Unbeliever 10.08.2018 14:38

Он не компилируется, он ничего не возвращает (и Action<T>, вероятно, здесь тоже ошибочен, поскольку он представляет собой метод void, вместо этого вам нужно использовать Func<T, TResult>)

bassfader 10.08.2018 14:38

@Che Спасибо за пример синтаксиса. Add () действительно отличается (поскольку он формируется из настраиваемого объекта ColumnCollection), а не напрямую из списка. Спасибо

lordvlad30 10.08.2018 14:44

@ lordvlad30 Тогда просто замените List <ColumnClass> на ColumnCollection. Думаю, это касается твоего случая. Я отредактировал ответ.

Che 10.08.2018 14:46
 public static class SomeClass
{
    public object void Columns(Func<Foo,object> action)
    {
        throw new Exception();
    }
}


public class Foo
{

    public Foo Add()
    {
        return this;
    }

    public Foo Value(object value)
    {
        return this;
    }

    public Foo Text(string text)
    {
        return this;
    }

}    

использовать так:

 SomeClass.Columns(columns =>
        {
            columns.Add().Text("SomeText");
            columns.Add().Value("SomeValue");

            return columns;
        });
Ответ принят как подходящий

Сначала вам нужен тип коллекции, который создает новый экземпляр и возвращает его при вызове «Добавить»:

interface IList<T>
{
    T Add();
}

Затем есть свободный класс Column:

class Column
{
    public Column Text(string text)
    {
        // Do stuff
        return this;
    }

    public Column Value(string value)
    {
        // Do stuff
        return this;
    }
}

Затем есть SomeClass, который позволяет пользователю указать действие для выполнения над «коллекцией»:

class SomeClass
{
    private static IList<Column> localList;

    public static void Columns(Action<IList<Column>> action)
    {
        // Perform action using localList as parameter
        action(localList);
    }
}

Это удовлетворяет синтаксису:

SomeClass.Columns(columns =>
{
    columns.Add()
        .Text("Product")
        .Value("123");

    columns.Add()
        .Text("Amount")
        .Value("456");
});

Спасибо за этот полный пример.

lordvlad30 10.08.2018 15:06

Другие вопросы по теме