Open13

Try C# on Arch Linux

ruka64(るか)ruka64(るか)

きっかけ

TypeScriptに飽きて、そろそろ別の言語を学んでみたくなったのでとりあえずC/C#/C++あたり学ぼうよとなって学ぶことに。
忘れないように色々メモっておく。

実行環境

  • OS: EndeavourOS (Arch)
  • Shell: bash
  • エディタ: VSCode
  • .NET Ver: 9.0.105

参考用

初期設定なり
https://zenn.dev/midoliy/articles/9e3cff958ff89ba151de
https://qiita.com/iota_11/items/5d805775ac2a42358427

チュートリアル
https://learn.microsoft.com/ja-jp/visualstudio/get-started/csharp/tutorial-console?view=vs-2022
https://ufcpp.net/

dotnet build
https://learn.microsoft.com/ja-jp/dotnet/core/tools/dotnet-build

シングルバイナリアプリケーションを作る上で参考にした
https://learn.microsoft.com/en-us/dotnet/core/deploying/single-file/overview?tabs=cli
https://qiita.com/skitoy4321/items/e8a43881456edc1f2c61
https://qiita.com/TsuyoshiUshio@github/items/8de754d3b94b7f762e6a

RIDs (win-x64, linux-x64など)
https://learn.microsoft.com/en-us/dotnet/core/rid-catalog#known-rids

EditorConfig
https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/code-style-rule-options?view=vs-2019

ruka64(るか)ruka64(るか)

.NET SDKインストール

sudo pacman -S dotnet-sdk

(VSCode) 以下の拡張機能をいれる

  • C# Dev Kit (C# + .NET Install Tool)
  • VS Sharper for C#
  • vscode-solution-explorer
ruka64(るか)ruka64(るか)

実行

dotnet run

これだけ。

ビルド

一つのバイナリファイルにまとめたいので、ちょっといじる
RuntimeIdentifierの箇所はWindowsであればwin-x64などにすること。詳しくはKnown RIDs

cstry.csproj
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net9.0</TargetFramework>
    <PublishSingleFile>true</PublishSingleFile>
    <SelfContained>true</SelfContained>
    <ImplicitUsings>enable</ImplicitUsings>
    <RuntimeIdentifier>linux-x64</RuntimeIdentifier>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>

そしてビルド

dotnet publish

成果物は/bin/Release/net9.0/linux-x64/publishにあった。

しっかり動いてる。

ruka64(るか)ruka64(るか)

dotnet formatdotnet-formatがあるので実行時間を比べる

dotnet format

time dotnet format cstry.csproj 

real    0m9.388s
user    0m8.768s
sys     0m0.435s

dotnet-format

time dotnet-format cstry.csproj 
  ワークスペース '.../try-csharp/cstry/cstry.csproj' でコード ファイルを書式設定します。
  コード ファイル '.../try-csharp/cstry/Program.cs' が書式設定されました。
  2608 ミリ秒で書式設定が完了します。

real    0m3.740s
user    0m3.598s
sys     0m0.217s

結構違う。

ruka64(るか)ruka64(るか)

ちょっとややこしくて苦しんでいるのが、dotnet newしたときに.csproj.slnの2つが生成されるせいで

$ dotnet format
Unhandled exception: System.IO.FileNotFoundException: MSBuild のプロジェクト ファイルとソリューション ファイルの両方が '/home/r64/workspace/try-csharp/cstry/' で見つかりました。使用するファイルを <workspace> 引数で指定してください。

となる問題。

めんどくさいな...
https://tutorialmore.com/questions-1712756.htm
https://qiita.com/TsuyoshiUshio@github/items/13c635d033322b175a5e

ruka64(るか)ruka64(るか)

チュートリアル通りに、電卓を作る

Program.cs
// Declare variables and then initialize to zero.
int num1 = 0; int num2 = 0;

// Display title as the C# console calculator app.
Console.WriteLine("Console Calculator in C#\r");
Console.WriteLine("------------------------\n");

// Ask the user to type the first number.
Console.WriteLine("Type a number, and then press Enter");
num1 = Convert.ToInt32(Console.ReadLine());

// Ask the user to type the second number.
Console.WriteLine("Type another number, and then press Enter");
num2 = Convert.ToInt32(Console.ReadLine());

// Ask the user to choose an option.
Console.WriteLine("Choose an option from the following list:");
Console.WriteLine("\ta - Add");
Console.WriteLine("\ts - Subtract");
Console.WriteLine("\tm - Multiply");
Console.WriteLine("\td - Divide");
Console.Write("Your option? ");

// Use a switch statement to do the math.
switch (Console.ReadLine())
{
  case "a":
    Console.WriteLine($"Your result: {num1} + {num2} = " + (num1 + num2));
    break;
  case "s":
    Console.WriteLine($"Your result: {num1} - {num2} = " + (num1 - num2));
    break;
  case "m":
    Console.WriteLine($"Your result: {num1} * {num2} = " + (num1 * num2));
    break;
  case "d":
    Console.WriteLine($"Your result: {num1} / {num2} = " + (num1 / num2));
    break;
}
// Wait for the user to respond before closing.
Console.Write("Press any key to close the Calculator console app...");
Console.ReadKey();

異なる箇所もあるが、構文は大体JavaScriptと似ている印象。switch case文辺りはほぼそっくりだろう

ruka64(るか)ruka64(るか)

Init & add Discord.Net pkg

dotnet new console && dotnet add package Discord.Net
ruka64(るか)ruka64(るか)

Docsを参考にコーディング

Program.cs
using Discord;
using Discord.WebSocket;

public class Program
{
    private static DiscordSocketClient? _client;

    public static async Task Main()
    {
        _client = new DiscordSocketClient();

        _client.Log += Log;

        var token = "token";

        await _client.LoginAsync(TokenType.Bot, token);
        await _client.StartAsync();

        // Block this task until the program is closed.
        await Task.Delay(-1);
    }

    private static Task Log(LogMessage msg)
    {
        Console.WriteLine(msg.ToString());
        return Task.CompletedTask;
    }
}
ruka64(るか)ruka64(るか)

ただ、このままだとtokenがハードコーディングされててghなどに公開すると大変な事になるのでconfig.jsonに記述させたものを使うようにする。

- var token = "token";
+ var jsonContent = File.ReadAllText("config.json");
+ var config = JsonConvert.DeserializeObject<ConfigClass>(jsonContent);
+ var token = config!.Token;

ConfigClassはこんな感じで。

public class ConfigClass {
  public string? Token {get; set;}
}

こっちの方がいいかも?

public class ConfigClass {
  public required string Token {get; set;}
}