iT邦幫忙

0

【C#學習筆記】05《元組(Tuple)與忽略(Discard)》

  • 分享至 

  • xImage
  •  

【C#學習筆記】04《整數與浮點數》
【C#學習筆記】06《字串與字元》


元組(Tuple)是用來回傳或儲存多個值的寫法技巧,忽略(Discard)則是丟棄特定的Tuple值。

範例:取得最大最小值

C#7.0之前,因為還沒有相關的語法,如果要回傳多個值,通常會使用out參數,或包裝成class/struct
雖然這樣做也可以,但在多參數的情況下,程式碼會變得冗長。而使用class/struct,雖然可讀性高,但變成次要資料也必須得用class/struct包起來

// tuple and discard, supported in C# 7.0 and later

//Before C# 7.0
void GetMinMaxOld(int a, int b, out int max, out int min)
{
    max = Math.Max(a, b);
    min = Math.Min(a, b);
}
//call
int max_old;
int min_old;

GetMinMaxOld(3, 10, out max_old, out min_old);

Console.WriteLine($"max_old = {max_old}");
Console.WriteLine($"min_old = {min_old}");

C#7.0之後,多了Tuple語法,程式碼就會簡潔許多。

// C# 7.0 and later
int GetMax(int a, int b) => a > b ? a : b;

// C# 7.0 and later supports tuples, so we can return both max and min in a single method
(int max, int min) GetMaxMin(int a, int b) => a > b ? (a, b) : (b, a);

var (max, min) = GetMaxMin(5, 10);
Console.WriteLine($"Max: {max}, Min: {min}");

var k = GetMaxMin(7, 17);
Console.WriteLine($"Max: {k.max}, Min: {k.min}");//recommended
Console.WriteLine($"Max: {k.Item1}, Min: {k.Item2}");//unrecommended, less readable

元組(Tuple)

Tuple主要用來「一次回傳或儲存多個值」,是一種輕量級的資料結構,能將多個不同型別的值組合在一起。
格式:

//(型別 名稱, 型別 名稱, .....)Tuple名稱
//宣告
(int x, int y) position;//一個包含x與y的Tuple-position
//賦值
position = (10, 20);
//取值
Console.WriteLine(position.x);
Console.WriteLine(position.y);

情境範例1

遊戲開發時,我們要取得玩家名稱等級HP,如果只使用一般的return,一次只能回傳一個值。我們改成使用Tuple:

// 回傳一個 Tuple
// Tuple 內包含:name、level、hp 三個值
(string name, int level, float hp) GetPlayerInfo(string playerName, int playerLevel, float playerHp)
{
    return (playerName, playerLevel, playerHp);// 將三個值打包成 Tuple 回傳
}
// 呼叫函式
// 回傳值會存進 player
var player = GetPlayerInfo("Player1", 10, 100.0f);
// 使用 Tuple 內的名稱存取資料
Console.WriteLine($"Name: {player.name}, Level: {player.level}, HP: {player.hp}");

情境範例2

取得物件座標:

(float x, float y) GetPosition() => (10.5f, 20.5f);
var (x, y) = GetPosition();
Console.WriteLine($"X: {x}, Y: {y}");//X: 10.5、Y: 20.5

Tuple用於switch判斷

void EasySample(int a, int b)
{
    switch(a , b)
    {
        case(> 0, > 0) when a == b:
            Console.WriteLine("same");
            break;
        case(> 0, > 0):
            Console.WriteLine($"first: {a}, second: {b}");
            break;
        default:
            Console.WriteLine($"not valid");
            break;
    }
}

EasySample(5, 5);
EasySample(5, 10);

忽略(Discard)

Discard用於忽略Tuple中的特定值

var (maxValue, _) = GetMaxMin(3, 8);// We only care about the max value, so we discard the min value using '_'
Console.WriteLine($"Max: {maxValue}");

_ = GetMaxMin(15, 5); // We don't care about the result, just want to call the method
GetMaxMin(5, 10);// We can also ignore the result of a method that returns a tuple

解構(Deconstruction)

解構是指將Tuple中的元素「拆解」並賦值給個別獨立的變數。這讓程式碼讀起來更像是在處理一般變數,而不是在操作一個物件。
上述提到的Discard其實也是解構的一種行為。

(int hp, bool isDead) TakeDamage(int hp, int damage)
{
    hp -= damage;
    return (hp, hp <= 0);
}

var result = TakeDamage(100, 30);

int hp = result.hp;
bool dead = result.isDead;

Console.WriteLine(hp);
Console.WriteLine(dead);

解構最酷的應用之一,就是不需要暫存變數temp 就能交換兩個變數的值:

int a = 5, b = 10;
(a, b) = (b, a);
Console.WriteLine($"a: {a}, b: {b}");

「這雖然使用了Tuple的語法結構,但編譯器會優化它,不會真的產生Tuple物件,是目前C#最推薦的數值交換方式。」


「總結來說,Tuple是C#提供給開發者的『輕量資料組合工具』。它並不是要取代Class,而是讓我們在處理『暫時性、小規模、關聯性強』的資料時,可以避免為了單純傳遞幾個值而額外建立型別。透過Tuple解構的搭配,程式碼通常能變得更簡潔,也更適合表達『多值回傳』這類情境。不過,Tuple更偏向資料傳遞工具;當資料開始具有明確語意、複雜邏輯、長期維護需求,或需要作為公開API與系統核心模型時,使用 Class、Record或其他明確型別,通常會有更好的可讀性與擴充性。」


圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言