😽

C#の予約語でミスチル曲紹介

2022/08/11に公開2

きっかけ

Enumerable.Anyメソッドって使わないなぁ🤔

https://twitter.com/nuits_jp/status/1556763573438664704?s=20&t=vyu2NAhCpTywLv84bK3mpw

if文に限らず、どんなケースでも使ったことない😎

余談

ツイートの主は、先日はてぶトップに上がっていた👇を書かれた御仁です

https://zenn.dev/nuits_jp/articles/2022-07-31-estimate-assumptions

イイネ数200越え!

そういえば

ミスチルの曲にAnyってあったなあ🤔

2002年、Mr.Childrenがシングル"Any"を制作。

キャプチャの出典はDeepL翻訳ツールです🤳

インスパイア・ド・バイ

Anyキーワードをどうしても使いたい!

https://ufcpp.net/blog/2022/5/consecutive-keywords/

👆まさに神々の遊び

できたもの

じゃじゃーん🐔

Program.cs
using System;
using System.Linq;

namespace workdir;

class Program
{
    [STAThread]
    static void Main(string[] args)
    {
        System.Windows.Controls.Grid Mr = new();
        var _ = (in DateTime _) => (2002, _.Year, Mr.Children.Cast<Single>().Any());
        Console.WriteLine("Hello, Zenn!");
    }
}

ここがミソ🐥

2002Mr以外はキーワード ―― C#が予約している言葉

Program.cs(一部抜粋)
var _ = (in DateTime _) => (2002, _.Year, Mr.Children.Cast<Single>().Any());

varを除けば、DeepL左辺になる🤡 なんて作為的な!

※ キャプチャは再掲です

ちゃんと実行できます

Visual Studio Codeターミナル
dotnet run

Hello, Zenn!

あとで気づいたこと

タプル型は禁じ手だったかも・・・いくらでもカンマ区切りで繋げられる

試行錯誤の過程

Visual Studio Codeを開きます
OSはWindows 11 Homeです

プロジェクトをつくる

.NET 5.0でつくり初めますが、すぐに.NET 6.0へ変更します

  • 理由は、最上位ステートメントを使いたくないからです
    • エントリポイントであるstatic Main()メソッドに、アトリビュートを付けたいからです
Visual Studio Codeターミナル
mkdir workdir
cd workdir
dotnet new console --framework="net5.0"
code workdir.csproj

https://docs.microsoft.com/ja-jp/dotnet/core/tutorials/top-level-templates#use-the-old-program-style

ターゲットを.NET 6へ変更する

ついでにWPFも有効にします
画面は使いませんが、画面の部品を使います

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

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <!-- 変更ここから -->
    <TargetFramework>net6.0-windows</TargetFramework>
    <UseWPF>true</UseWPF>
    <!-- 変更ここまで -->
  </PropertyGroup>

</Project>

Program.csを書き換える

いったん実行してみて、ハローワールドしてくれることを確認する

Visual Studio Codeターミナル
code Program.cs  
dotnet run     

Hello World!

Main()にアトリビュートをつける

[STAThread]をつけないと、👇と怒られる

Unhandled exception. System.InvalidOperationException: 呼び出しスレッドは、多数の UI コンポーネントが必要としているため、STA である必要があります。

Program.cs(一部抜粋)
[STAThread]
static void Main(string[] args) { /* ... */ }

Children探し

C# ChildrenでWeb検索すると、WPFの画面部品であるパネルがヒットする

  • PresentationFramework.dllを使うために、.csprojUseWPFを有効にした
  • .Childrenの型はUIElementCollectionであり、IEnumerableの実装である。IEnumerable<T>の実装ではない。
    • Children.Any()Children.Select()などは不可

ラムダ式をvarで受けられるのは、.NET 6.0から

ターゲットを.NET 5.0に落として実行すると、👇と怒られる

'推論されたデリゲート型' は C# 9.0 では使用できません。言語バージョン 10.0 以上を使用してください。

C# 10.0、すなわち.NET 6.0以上が要件
wikipediaにC#のバージョンとフレームワークの対応表が載っている)

https://docs.microsoft.com/ja-jp/dotnet/csharp/whats-new/csharp-10#lambda-expression-improvements

.NET 5.0以前は、ラムダ式の入力部にinがつけられない?

つけると構文エラーを指摘される

// .NET 5.0 では左辺を var にできないので、愚直に Func を書く
Func<DateTime, (int, int, bool)> _ = (DateTime _) => // ...

// さらには、ラムダ式の入力に in キーワードをつけられない
// (つけると構文エラーになる・・・なぜだろう)
Func<DateTime, (int, int, bool)> _ = (in DateTime _) => // ... <-構文エラー

エラー CS1677 パラメーター 1 はキーワード 'in' で宣言しないでください

エラー CS1661 パラメーター型がデリゲート パラメーター型と一致しないため、ラムダ式 を型 'Func<DateTime, (int, int, bool)>' に変換することはできません

左辺をvarにすれば上記エラーは発生しない
すなわち、左辺をvarにできない.NET 5.0以前では、ラムダ式の入力にinがつけられない(と思う)

NET6で検証
var f1            = (in int x) => x; // OK
Func<int, int> f2 = (in int x) => x; // 構文エラー

おわりに

.Any()を使うシチュエーションを考えてたら思いついただけ記事でした

適当なテーマ設定の割に、調べものしないと詰まる所があり、少しは蓄えになったと信じたい

参考にさせていただいたサイト

http://blog.syo-ko.com/?eid=2918

https://social.msdn.microsoft.com/Forums/en-US/d23e49d6-d96f-424f-8c90-92e0783e717f/why-does-linq-not-work-directly-against-uielementcollection?forum=wpf

https://zenn.dev/midoliy/articles/9e3cff958ff89ba151de

Discussion

VVIIVVII

DateTime も Singleも標準ライブラリで提供されているだけのただの構造体やクラスではないでしょうか?

これがOKならそれこそいくらでも繋げられるのでは?

t13801206t13801206

コメントありがとうございます!

おっしゃる通りでDateTimeSingleも標準ライブラリのクラスなので
いくらでも繋げられてしまいますね。
予約語ではないという意味では、記事タイトルもまずかったかもです。

趣旨としましては、なるべく予約語や標準ライブラリのみで
単語をつなげて文章を作ろうと思った次第ですので
そのように受け取っていただければと幸いです。