Есть ли практические примеры кортежей для начинающих программистов?

Я делаю учебное видео для С# 4.0 для начинающих программистов.

Для каждой темы, которую я представляю, я включаю практический пример , который студент мог бы использовать, например, для улучшенной функциональности COM Interop, я показываю, как создайте файл Excel и заполните его значениями из кода.

Для параметров и параметров параметров. Я показываю, как вы можете создать метод ведения журнала с 5 параметрами, но не нужно передавать какие-либо, если вы не хотите, поскольку все они имеют значения по умолчанию. Таким образом, они видят, как методы вызова проще с этой функцией.

Я также хотел бы представить кортежи, если можно, но кажется, что все "практические примеры" (как в этом вопросе: Практические пример, где Tuple можно использовать в .Net 4.0?) очень продвинуты. Учащиеся, которые используют видео, изучают ООП, LINQ, используя дженерики и т.д., Но, например, функциональное программирование или "решение проблемы 11 Project Euler" выходят за рамки этого видео.

Может ли кто-нибудь подумать о примере, где кортежи действительно были бы полезны начинающему программисту или примеру, где они могли бы по крайней мере понять, как они могут быть использованы и продвинутым программистом? Их механика довольно прямолинейна - Чтобы начинающий программист мог понять, я хотел бы просто найти пример, чтобы ученик мог фактически использовать их по практической причине. Любые идеи?

Вот что я до сих пор, но это просто сухая механика без какой-либо функциональности:

using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            //two ways to define them
            var customer = new Tuple<int, string, string>(23, "Sam", "Smith");
            var customer2 = Tuple.Create<int, string, string>(34, "James", "Allard");

            //with type inference, more concise (only available with the Create keyword)
            var customer3 = Tuple.Create(23, "John", "Hoopes");

            //you can go up to eight, then you have to send in another tuple
            var customer4 = Tuple.Create(1, 2, 3, 4, 5, 6, 7, Tuple.Create(8, 9, 10));

            Console.WriteLine(customer.Item1);
            Console.WriteLine(customer2.Item2);
            Console.WriteLine(customer3.Item3);
            Console.WriteLine(customer4.Rest.Item1.Item3);

            Console.ReadLine();
        }
    }
}

Ответы

Ответ 1

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

То, что приходит на ум, возвращает значение (которое может фактически быть нулевым) от функции, которая выполняет поиск (или вычисление) вместе с логическим значением, указывающим, был ли найден результат или нет. Это подход, который позволяет избежать использования параметров, которые могут быть громоздкими или проблематичными в определенных сценариях (например, запросы LINQ):

public Tuple<string,bool> SearchDictionary( string searchKey )
{
    string value;
    bool wasFound = someDictionary.TryGetValue( searchKey, out value );
    return new Tuple<string,bool( value, wasFound );
}

// since <null> is a legal value to store in the dictionary, we cannot
// use it to distinguish between 'value not found' and 'value is null'.
// the Tuple<string,bool>, however, does allow us to do so...
var result = SearchDictionary( "somekey" );
if( result.Item2 )
{
    Console.WriteLine( result.Item1 );
}

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

// note the symmetry in the representation of opponents of a tennis match...
// if the relationship were asymmetrical, tuple may not be the best choice.
var playerA  = new TennisPlayer("Serena Williams");
var playerB  = new TennisPlayer("Venessa Williams");
var match    = new Tuple<TennisPlayer,TennisPlayer>( playerA, playerB );

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

В последнем примере используются кортежи для представления составных клавиш в словаре. Поскольку Tuple<> можно сравнивать друг с другом для равенства, становится возможным делать такие вещи, как:

var complexDictionary = 
      new Dictionary<Tuple<string,int,decimal,DateTime>,string>();
complexDictionary.Add( new Tuple("USA",-4,1.671,DateTime.Now), "active" );

EDIT: Один комментарий, который я хотел бы сделать при обучении разработчиков использованию кортежей, заключается в том, что кортежи должны редко (если вообще когда-либо) появляться в общедоступном интерфейсе кода, который вы ожидаете от других, чтобы потреблять. Как инструменты для упрощения внутренней реализации класса или модуля, я думаю, что все в порядке. Но как только вы начнете передавать их в или из методов, с которыми разработчики, потребляющие ваш код, должны взаимодействовать, вы запускаете в проблеме, что кортежи скрывают семантику вашего API. Разработчикам становится трудно понять, что означает Tuple<int,int>. Что означает Item1 или Item2 в таком случае? Когда вы видите, что вам нужно передавать кортежи в или из методов, вам следует настоятельно рассмотреть возможность написания класса для инкапсуляции и уточнения отношений.

Ответ 2

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

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

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

Ответ 3

Я использую их вместо частных классов. Отличные при использовании внутри в классе. Выявление их вне класса привело лишь к путанице. Мне пришлось открыть класс, чтобы определить, что именно.

Ответ 4

Как насчет формы входа? Они все это видят.

var loginCredentials = 
    new Tuple<string, SecureString>(nameTextBox.Text, passwordTextBox.Text);

if (Login(loginCredentials))
    Console.Writeline("Login - Success!");
else
    Console.Writeline("Login - Failure");

...

public bool Login(Tuple<string, SecureString> loginCredentials)
{
    return ...
}