首页 > 编程语言 >C#教程 - 元组与解构(Tuples and Deconstruction )

C#教程 - 元组与解构(Tuples and Deconstruction )

时间:2023-10-10 10:47:53浏览次数:39  
标签:Console name 23 C# Tuple 解构 Tuples WriteLine Bob

C#教程 - 元组与解构(Tuples and Deconstruction )

 

更新记录
转载请注明出处:
2022年9月24日 发布。
2022年9月10日 从笔记迁移到博客。

元组(tuples)说明#

注意:C# 7.0可用
注意:元组不可以声明为静态类型
作用:元组常用于传递和返回多个值;匿名类型可以做的,Tuples基本都可以完成
元组是可变的(mutable),可以直接修改元组的成员
需要System. ValueType<T,T…>泛型类型支持
这个类型并非.NET Framework 4.6的一部分,4.7版本包含这个类型
注意:元组(Tuple)是值类型(value types),是可变类型(mutable (read/write))
tuple可以不定义元素名称,也可以定义命名Tuple元素(Naming Tuple Elements)

实例:

var bob = ("Bob", 23);
var joe = bob;                     // joe is a *copy* of bob
joe.Item1 = "Joe";                 // Change joe's Item1 from Bob to Joe
Console.WriteLine (bob);           // (Bob, 23)
Console.WriteLine (joe);           // (Joe, 23)

定义元组#

注意:命名元素后,仍然可以使用Item1这样的方式访问元素

注意:如果定义时,使用了外部的变量,可以直接使用.外部变量名方式访问

注意:tuple之间可以相互赋值,只要类型之间是兼容的

显式定义#

实例:定义Tuple

var bob = ("Bob", 23); // Allow compiler to infer the element types
Console.WriteLine (bob.Item1); // Bob
Console.WriteLine (bob.Item2); // 23

实例:

//显式定义
(string name, int age, long code) panda1 = ("Panda1", 18, 666);
Console.WriteLine(panda1.name);
Console.WriteLine(panda1.age);
Console.WriteLine(panda1.code);

隐式定义#

//隐式定义1
var panda2 = ("Panda2", 18, 888);
Console.WriteLine(panda2.Item1);
Console.WriteLine(panda2.Item2);
Console.WriteLine(panda2.Item3);
//隐式定义2(Naming Tuple Elements)
var panda3 = (name: "Panda3", age: 18, code: 666);
Console.WriteLine(panda3.name);
Console.WriteLine(panda3.age);
Console.WriteLine(panda3.code);

更多实例:
实例:

var tuple = (name:"Bob", age:23);
Console.WriteLine (tuple.name);     // Bob
Console.WriteLine (tuple.age);      // 23

实例:

static (string name, int age) GetPerson() => ("Bob", 23);

实例:

(string name, int age, char sex)  bob1 = ("Bob", 23, 'M');

实例:定义Tuple(显式类型)

(string,int) bob = ("Bob", 23);

实例:定义tuple带元素命名

var tuple = (name:"Bob", age:23);
Console.WriteLine (tuple.name); // Bob
Console.WriteLine (tuple.age); // 23

实例:Tuple是值类型测试

var bob = ("Bob", 23); // Allow compiler to infer the element types
Console.WriteLine (bob.Item1); // Bob
Console.WriteLine (bob.Item2); // 23
var joe = bob; // joe is a *copy* of bob
joe.Item1 = "Joe"; // Change joe's Item1 from Bob to Joe
Console.WriteLine (bob); // (Bob, 23)
Console.WriteLine (joe); // (Joe, 23)

实例:直接使用外部变量名来访问

var now = DateTime.Now;
var tuple = (now.Day, now.Month, now.Year);
Console.WriteLine (tuple.Day); // OK

实例:方法返回tuple类型

static (string,int) GetPerson() => ("Bob", 23);

实例:方法返回tuple类型带命名

static (string name, int age) GetPerson() => ("Bob", 23);
var person = GetPerson();
Console.WriteLine (person.name); // Bob
Console.WriteLine (person.age); // 23

实例:tuple用在泛型类型中

Task<(string,int)>
Dictionary<(string,int),Uri>
IEnumerable<(int id, string name)> // See below for naming elements

实例:类型兼容的赋值

(string name, int age, char sex) bob1 = ("Bob", 23, 'M');
(string age, int sex, char name) bob2 = bob1; // No error!

元组作为返回值#

简单元组返回值

using System;
using System.Runtime.Versioning;

namespace ConsoleApp1
{
    class PandaClass
    {
        //实例
        public (string,int) DoSomething()
        {
            return ("Panda", 666);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            PandaClass pandaClass = new PandaClass();
            //测试
            (string,int) result = pandaClass.DoSomething();
            Console.WriteLine(result.Item1); //Panda
            Console.WriteLine(result.Item2); //666

            //wait
            Console.ReadKey();
        }
    }
}

元组返回值 与 泛型 结合使用

using System;
using System.Collections.Generic;
using System.Runtime.Versioning;

namespace ConsoleApp1
{
    class PandaClass
    {
        //实例
        public List<(string, int)> DoSomething()
        {
            return new List<(string, int)> { ("Panda", 666) };
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            PandaClass pandaClass = new PandaClass();
            //测试
            List<(string, int)> result = pandaClass.DoSomething();
            Console.WriteLine(result.Count); //1
            Console.WriteLine(result[0].Item1); //panda
            Console.WriteLine(result[0].Item2); //666

            //wait
            Console.ReadKey();
        }
    }
}

元组返回值 与 成员命令

using System;
using System.Collections.Generic;
using System.Runtime.Versioning;

namespace ConsoleApp1
{
    class PandaClass
    {
        //实例
        public List<(string website, int code)> DoSomething()
        {
            return new List<(string, int)> { ("Panda", 666) };
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            PandaClass pandaClass = new PandaClass();
            //测试
            List<(string website, int code)> result = pandaClass.DoSomething();
            Console.WriteLine(result.Count); //1
            Console.WriteLine(result[0].website); //panda
            Console.WriteLine(result[0].code); //666

            //wait
            Console.ReadKey();
        }
    }
}

元组解构(Deconstructing Tuples)#

Tuples implicitly support the deconstruction pattern

//显式解构
(string name, int age, int code) = ("Panda", 18, 666);
Console.WriteLine(name);
Console.WriteLine(age);
Console.WriteLine(code);
//隐式解构
(var name, var age, var code) = ("Panda", 18, 666);
Console.WriteLine(name);
Console.WriteLine(age);
Console.WriteLine(code);
//使用现有变量
string name;
int age;
int code;
(name, age, code) = ("Panda", 18, 666);
//省略不需要的数据(使用下划线代替即可)
(string name, _, int code) = ("Panda666", 18, 666);
Console.WriteLine(name);
Console.WriteLine(code);

实例:

var bob = ("Bob", 23);
(string name, int age) = bob;
Console.WriteLine (name);
Console.WriteLine (age);

实例:从方法返回值中解构

static (string, int, char) GetBob() => ( "Bob", 23, 'M');
static void Main()
{
    var (name, age, sex) = GetBob();
    Console.WriteLine (name); // Bob
    Console.WriteLine (age); // 23
    Console.WriteLine (sex); // M
}

元组的本质#

匿名类型会在底层定义自定义类型

元组在底层使用预定义的System.ValueTuple<T,T…>泛型结构

public struct ValueTuple<T1>

public struct ValueTuple<T1,T2>

public struct ValueTuple<T1,T2,T3>

//...

每种ValueTuple都会定义Item1,Item2,...这样的属性

所以 (string,int) 是 ValueTuple<string,int>的别名

命名参数的Tuplue会在编译的时候,将自定义命名转为Item1,...这样的属性

比如:(string,int)在后台被转为 ValueTuple<string,int>

ValueTuple<string, int, int> s = ValueTuple.Create("Panda666", 18, 666);
Console.WriteLine(s.Item1);
Console.WriteLine(s.Item2);
Console.WriteLine(s.Item3);

有个例外是在方法返回命名Tuple时,会保留命名属性

底层使用TupleElementNamesAttribute特性来实现的

ValueTuple.Create#

除了定义式声明Tuple,还可以使用Create工厂方法来创建Tuple

注意:这种方式无法定义命名的Tuple。因为命名Tuple是编译器实现的

实例:

ValueTuple<string,int> bob1 = ValueTuple.Create ("Bob", 23);
(string,int) bob2 = ValueTuple.Create ("Bob", 23);

元组的比较(Tuple Comparison)#

ValueTuple在底层重写了Equal方法,可以直接使用,只要是成员顺序和值相同

ValueTuple<> overloads the == and != operators,从C# 7.3开始

元组还实现了IComparable接口,所以可以作为排序的键

ValueTuple<> also implement IComparable

实例:

using System;
using System.Collections.Generic;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            var panda1 = ("Panda666.com",666);
            var panda2 = ("Panda666.com",666);
            Console.WriteLine(panda1 == panda2);      //true
            Console.WriteLine(panda1.Equals(panda2)); //true
            
            //wait
            Console.ReadKey();
        }
    }
}

实例:

var t1 = ("one", 1);
var t2 = ("one", 1);
Console.WriteLine (t1 == t2);    // True (from C# 7.3)
Console.WriteLine (t1.Equals (t2));    // True

实例:使用Equals方法

var t1 = ("one", 1);
var t2 = ("one", 1);
Console.WriteLine (t1.Equals (t2)); // True
Console.WriteLine (t1 == t2); // 使用==运算符,True

元组与System.Tuple类型#

Tuple在.NET Framework 4.0中引入

System.Tuple是一个类,而System.ValueType是一个泛型结构

Tuple没有C#语言支持,而元组有

优先考虑使用ValueTuple

实例:

Tuple<string,int> t = Tuple.Create ("Bob", 23); // Factory method
Console.WriteLine (t.Item1); // Bob
Console.WriteLine (t.Item2); // 23

Tuple实例:

using System;
using System.Collections.Generic;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            Tuple<string, int> tuple1 = new Tuple<string, int>("Panda", 666);
            Tuple<string, int> tuple2 = Tuple.Create("Panda", 666);
            Console.WriteLine(tuple1.Item1); //Panda
            Console.WriteLine(tuple1.Item2); //666
            Console.WriteLine(tuple2.Item1); //Panda
            Console.WriteLine(tuple2.Item2); //666

            //wait
            Console.ReadKey();
        }
    }
}

作者:Panda666

标签:Console,name,23,C#,Tuple,解构,Tuples,WriteLine,Bob
From: https://www.cnblogs.com/sexintercourse/p/17754014.html

相关文章

  • c#入门-解构方法
    解构方法解构方法可以让实例能像元组一样被析构,或使用模式匹配的位置模式。解构方法是公开无返回值的,名为Deconstruct的方法。所有参数均为out参数。vara=newTask();var(b,c)=a;classTask{publicvoidDeconstruct(outinta,outintb){a=b=0;}}......
  • 微软正式发布 C# 10,支持.NET 6 和 Visual Studio 2022 (附更新内容大全)
    微软正式发布C#10,支持.NET6和VisualStudio2022(附更新内容大全)2022/2/1211:24:36 来源:IT之家 作者:潇公子 责编:潇公子评论:0IT之家 2月12日消息,据微软中国MSDN,宣布C#10作为.NET6和VisualStudio2022的一部分已经发布了。在这篇文章中,微软将介绍C#......
  • Educational Codeforces Round 152 (Div. 2) D. Array Painting(双指针)
    EducationalCodeforcesRound152(Div.2)D.ArrayPainting//思路:双指针找连续正数段//若段中出现2,则更新两头的0的情况,若为涂色则改为true//若无2,则优先更新左侧0,若左0已经为true,则更新右侧0//数组开头结尾特判#defineintlonglong#defineldlongdoubleusingnam......
  • oracle中to_char(), to_date() ,ROUND(),NVL(), DECODE(), EXTRACT()等函数的使用
    1.to_char()将时间日期按照指定的格式输出,得到的是字符串,而非date类型。只要被转换的是一个日期,yyyy,mm,dd中间加不加连接符,加什么连接符都可以2.todate()将字符串按照指定的格式输出,得到的是日期类型。第一个参数的yyyy,mm,dd之间有没有连接符。如果有,那么第二个参数必须有......
  • channel 通道错误的使用例子
    1.向已经关闭的通道发送值,引起panic错误packagemainimport"fmt"funcrecv(cchanint){ ret:=<-c fmt.Println("接收成功",ret)}funcmain(){ ch:=make(chanint) gorecv(ch)//启用goroutine从通道接收值 ch<-10 close(ch) ch<-9 fmt.Prin......
  • 【题解】Fibonacci-ish II
    传送门题目分析根据题目范围\(n\le30000\)并且此题可以离线维护这个很恶心的东西,所以我们考虑莫队。由于要求访问到任意一个区间都要求知道它有序之后的序列,所以这个东西可以用权值线段树维护。因此,此题正解是莫队+权值线段树。我们分类讨论一下加上一个数,删除一个数对答案......
  • C# 12 中的新增功能
    C#12中的新增功能 新的C#12功能在预览版中已经引入.您可以使用最新的VisualStudio预览版或最新的.NET8预览版SDK来尝试这些功能。以下是一些新引入的功能:主构造函数集合表达式默认Lambda参数任何类型的别名内联数组拦截器使用nameof访问实例成员......
  • centos8添加永久路由
    linux配置静态路由,一般使用iprouteadd添加临时路由,重启会丢失配置永久配置路由方法:touch/etc/sysconfig/network-scripts/route-ens192nmcliconnectionmodifyens192+ipv4.routes"10.0.3.0/24192.168.2.254"nmclicreloadnmclicupens192编辑脚本封装多个命令,一......
  • ftrace在应用上的使用
    之前介绍通过命令行配置和使用ftrace功能,但是实际中,我们也会希望抓C/C++程序中某段代码的调度情况。笔者前不久就遇到这种问题,某个函数调用时延概率超过100ms,是为什么?这时候就需要在他们代码中使能ftrace抓执行此函数时候,任务的调度情况。观察某段代码执行过程中的情况,ftrace提供......
  • 练习记录-cf-Educational Codeforces Round 156 (Rated for Div. 2)(A-C)
    好久没打了还是就出了三道不过还好没掉分A.SumofThree就是问能不能把一个数拆成三个不同的且都不能被三整除的数我的思路就是拆成1+2+一个大于等于4的数如果拆了后另一个数是%3==0那么我拆成1+4它肯定就不被整除然后判下相同#include<bits/stdc++.h>#defineclose......