Как назвать свойства кортежа?

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

private static Tuple<string, string> methodTuple()
{
    return new {Name = "Nick", Age = "Twenty"}; /*exception because need to new Tuple<string, string>(){Item1 = "Nick", Item2 = "Twenty"}o*/
}

и вызывать такие параметры, как methodTuple.Name, а не methodTuple.Item1....N

Это возможно или нет?

UPD: я хочу создать объект с именованными параметрами без нового именованного типа.

Ответ 1

Для этого вам нужно объявить вспомогательный класс.

public class MyResult
{
    public string Nick { get; set; }
    public string Age { get; set; }
}

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

Анонимные типы (Руководство по программированию в С#)

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

Обновление

С# 7 представляет встроенную в язык поддержку Tuple и поставляется с именованными кортежами

(string name, int age) methodTuple()
{
    (...)
}

Узнайте больше на docs.microsoft.com: https://docs.microsoft.com/en-us/dotnet/articles/csharp/csharp-7#tuples

Ответ 2

В С# 7.0 (Visual Studio 2017) есть новая опция:

(string first, string middle, string last) LookupName(long id)

Ответ 3

Это невозможно с помощью Tuple, no. Для этого вам нужно создать свой собственный новый тип.

Ответ 4

Начиная с С# v7.0, теперь можно присваивать имена свойств кортежа, которые ранее использовались по умолчанию, именам, таким как Item1, Item2 и так далее.

Называя свойства Tuple Literals:

var myDetails = (MyName: "RBT_Yoga", MyAge: 22, MyFavoriteFood: "Dosa");
Console.WriteLine($"Name - {myDetails.MyName}, Age - {myDetails.MyAge}, Passion - {myDetails.MyFavoriteFood}");

Вывод на консоль:

Имя - RBT_Yoga, Возраст - 22, Страсть - Dosa

Возврат кортежа (с именованными свойствами) из метода:

static void Main(string[] args)
{
    var empInfo = GetEmpInfo();
    Console.WriteLine($"Employee Details: {empInfo.firstName}, {empInfo.lastName}, {empInfo.computerName}, {empInfo.Salary}");
}

static (string firstName, string lastName, string computerName, int Salary) GetEmpInfo()
{
    //This is hardcoded just for the demonstration. Ideally this data might be coming from some DB or web service call
    return ("Rasik", "Bihari", "Rasik-PC", 1000);
}

Вывод на консоль:

Данные сотрудника: Расик, Бихари, Расик-ПК, 1000

Создание списка кортежей с именованными свойствами

var tupleList = new List<(int Index, string Name)>
{
    (1, "cow"),
    (5, "chickens"),
    (1, "airplane")
};

foreach (var tuple in tupleList)
    Console.WriteLine($"{tuple.Index} - {tuple.Name}");

Вывод на консоль:

1 - корова 5 - куры 1 - самолет

Я надеюсь, что я охватил все. В случае, если есть что-то, что я пропустил, пожалуйста, дайте мне отзыв в комментариях.

Примечание. В моих фрагментах кода используется функция интерполяции строк С# v6, как подробно описано здесь.

Ответ 5

Обычно я создаю новый тип, полученный из Tuple, и сопоставляю ваши явные свойства, чтобы вернуть свойства базового класса ItemX. например:

public class Person : Tuple<string, string>
{
    public Key(string name, string age) : base(name, age) { }

    public string Name => Item1;
    public string Age => Item2;
}

Ответ 6

К сожалению, это невозможно с использованием типа "Tuple", поскольку он определен как "Item1... N" в MSDN. Таким образом, это исключение действительно.

Этот метод может быть скомпилирован тремя способами: 1.) Измените тип возврата на объект - это создаст "анонимный" тип, который вы затем сможете использовать позже. Это не особенно полезно, если вы хотите позже получить доступ к свойству "Имя" или "Возраст" без дополнительной работы. 2.) Измените тип возвращаемого значения на динамический - это позволит вам получить доступ к свойствам "Имя" и "Возраст", но сделает всю программу (только DLL, где этот метод находится на самом деле) несколько медленнее, поскольку использование динамического требует метания из-за сильной типизации. 3.) Создайте класс и используйте его как возвращаемый тип.

Пример кода здесь:

private static object ObjectTuple()
        {
            return new { Name = "Nick", Age = "Twenty" };
        }

        private static dynamic DynamicTuple()
        {
            return new { Name = "Nick", Age = "Twenty" };
        }

        private static Temp TempTuple()
        {
            return new Temp{ Name = "Nick", Age = "Twenty" };
        }

        class Temp
        {
            public string Name { get; set; }
            public string Age { get; set; }
        }

Ответ 7

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

 public CustomReturn ExecuteTask( int a, string b, bool c, object d )
        {
        // Calling constructor of CustomReturn Class to set and get values
          return new CustomReturn(a,b,c,d);
        }

        internal class CustomReturn 
        // for tuple inherit from Tuple<int,string,bool,object,double>
        { 
          //for tuple public int A{ get {this.Item1} private set;}

          public int A{get;private set;}
          public string B{get;private set;}
          public bool C{get;private set;}
          public object D{get;private set;}

          public CustomReturn (int a, string b, bool c, object d )
              // use this line for tuple ": base( obj, boolean )"
            {
              this.A = a;
              this.B = b;
              this.C = c;
              this.D = d;
            }

        }

    Main(args)
    {
      var result = ExecuteTask( 10, "s", true, "object" );
      // now if u have inherited Tuple for CustomReturn class then 

      // on doing result. you will get your custom name as A,B,C,D for //Item1,Item2,Item3,Item4 respectively also these Item1,Item2,Item3,Item4 will also be there.
    }

Ответ 8

Вы можете попробовать динамически:

    private static dynamic methodTuple()
    {
        return new { Name = "Nick", Age = "Twenty" }; 
    }

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