2022年5月20日金曜日

登記事項証明書をオンライン請求してみた!

とある申請のため、登記事項証明書を取得する必要がありました。
オンライン請求すると手数料が安いということもあり、初めて登記・供託オンライン申請システムを使い、請求してみました。


申請者情報の登録


登記・供託オンライン申請システムを使用するには、申請者情報登録、つまりユーザー登録が必要です。


メールアドレスがIDになるわけではなく、自分でIDを決めなければいけないのが面倒ですね。
最終利用から1年が経過すると、申請者情報削除通知メールが送られ、そこから30日以内にログインしないと自動的に削除されます。削除されると、同じIDで再登録することができません。


請求


システムには古さを感じますが、「登記・供託オンライン申請システム 申請者操作手引書 ~商業・法人 かんたん証明書請求編~」という操作手引書が公開されており、それに従えば請求手続きは難しくありません。

まず、請求に必要な情報を入力します。今回は、窓口で受け取るので、交付方法に「窓口受取」を選択し、受取場所に最寄りの法務局を指定します。


情報入力後、請求情報を送信します。


納付


処理状況を確認すると、送信後すぐには「納付」ボタンは表示されませんが、しばらくすると表示されます。


納付ボタンを押し、処理を進めると、e-Govの電子納付画面に遷移します。


利用している金融機関を選び、銀行のサイトにログインすると、払込先情報が入力され、すぐにPay-easyによる払込ができる状態になっています。これは非常に便利でした。

払込が完了すると、「納付済み」にステータスが変わります。

受取


処理状況が「手続終了」になると、法務局での受取が可能です。


受取時に何が必要か分からず、とりあえず申請番号だけをメモして法務局に向かいました。通常の申請窓口とは違う窓口で、オンライン請求した旨を伝えると、氏名、住所、請求通数、そして申請番号を紙に記入し、無事に証明書を受領することができました。

実はこの記事を書くにあたり、初めて手引書を見たのですが、そこに

請求した証明書を登記所の窓口で受け取る場合には,「処理内容照会(電子納付情報表示)」画面を印刷し,あらかじめ設けてある記載欄に, 請求に係る通数を記載したものを登記所の窓口に提出していただく必要があります。

と書かれていました。これを持参すれば、よりスムーズに受け取ることができますね。


またいつか、どこかで。

2022年5月15日日曜日

Pixel Buds購入、ワイヤレスイヤホンは探せる方がいい

こんにちは、やっまむーです。

先日のことです。

紛失!!

ワイヤレスイヤホンの利用者が必ずやるという片耳紛失、私もついにやってしまいました。
ちゃんとケースに入れたんです、それなのに何故か無い。
鞄の中も、直前に立ち寄った場所も探しましたが結局見つかりませんでした。
片耳だけでは使えませんし、今更有線のイヤホンには戻りたくありません。
泣く泣く新しいものを買うことにしました。

タイミングよく、Google StoreのセールでPixel Budsのセールが行われていたので購入しました。
決めてはGoogleの「デバイスを探す」サービスが使えることでした。

「デバイスを探す」サービスとは

「デバイスを探す」サービスはGoogleが提供している文字通り、Android端末を探しだすサービスです。
アカウントに紐づいているデバイスの現在位置を確認したり、音を鳴らしたり、リモートでデバイスの保護をすることができます。(※.利用のための設定は必要です)

Pixel Budsはこのサービスに対応しており、万が一紛失したとしても最後の位置情報を知ることができます。
またいつ何時、紛失するかわからないので、保険のためにサービス利用の設定を行いました。

ペアリングから設定までの手順

まずはスマホとPixel Budsのペアリングを行います。

Pixel Budsの場合、ペアリング時にGoogleアカウントとの関連付けが行われます。
接続すると、他のBluetooth機器とは異なる専用の設定画面になります。

「デバイスを探す」の画面では接続中のイヤホンから音を鳴らしたり、最後に接続した場所の確認ができます。

最後に接続した場所の確認には、Androidアプリの「デバイスを探す」が必要になります。
もしインストールされていなければ、ここでインストールを促されます。
インストール済みであれば、Pixel Budsが関連付けられたアカウントで「デバイスを探す」にログインすると、最後に接続した場所、時間が確認できます。

これで再び落としたとしても効率よく探すことができます。
まあ、そもそも落とさないようにするのが一番ですけどね。

ではではー。

2022年4月24日日曜日

WindowsPCの起動が重い時はこれを確認して欲しい。高速スタートアップ設定!

 


こんにちは。よっしーです。

Windowsを使っていると、なんか起動が重たいな?

っていう時がありませんか?

今までは普通に1分ぐらいで起動していたものが、

ある日を境に起動に5分ぐらいかかったり。。。


はい。私もそんな現象が起きました。

で、何が重たいんやろう。。。と思って、

タスクマネージャーを開いたんですが、

なんか稼働時間がえらいことになっていました。


これ、6日と6時間37分9秒 稼働しっぱなしですよ。という意味です。

実際に起動の重たかったPCは56日ぐらい稼働しっぱなしでした。。。


毎日シャットダウンしているし、バグってるのかな?と思って調べてみたのですが、

実は最近のWindowsOSは、普通にシャットダウンしても完全に停止している

わけではなく、スリープや休止状態になっているようです。


なので、一度不安定な状態になってしまうと、PCをシャットダウンしているつもりが、

スリープ、休止状態になっていて、PCを立ち上げると、スリープ、休止状態から

の復帰となるため、不安定な状態からスタートしてしまうことになります。


それを回避するためには、

(1) 高速スタートアップ設定を解除する

(2) Shiftを押しながらシャットダウンで、完全シャットダウンする

という2つの方法があります。


(1) 高速スタートアップ設定を無効化する

設定で高速スタートアップ設定を解除することで、シャットダウン時は

スリープや休止状態にならず、完全に電源OFF状態になります。



(2) Shiftを押しながらシャットダウンで、完全シャットダウンする

これはもうそのままですが、Shift押しながらシャットダウンや再起動を選択すると、

完全シャットダウンという扱いになり、スリープや休止状態にはならずに電源OFFします。


いかがだったでしょうか。

OSがどういった振る舞いをしているかをきちんと理解した上で、

設定をカスタマイズする必要があるので、初心者には難しいかもしれませんが

起動が重たい。というのはよく出てくる話です。

膨大な稼働時間が表示されている場合は、高速スタートアップを疑ってみて下さい。

ではまた~。

2022年4月15日金曜日

届書作成プログラムを使ってみた!

以前、自社でマイナポータルAPIを利用したソフトを開発した記事を書きました。


これまで手続きした算定基礎届、賞与支払届の届け出にあたっては、士業の先生から提出ファイル(KPFD0006.csv)をもらっていました。今回、被保険者資格取得届の提出にあたり、初めて「届書作成プログラム」を使用して、提出ファイルを作成しました。


届書作成プログラムのインストールと設定


届書作成プログラムは日本年金機構のサイトからダウンロードすることができます。
インストール後、事業所情報、健康保険組合情報を登録します。


提出ファイルの作成


届書作成プログラムで提出ファイルを作成することができるのですが、その前にまず届書を作成しなければなりません。届書ファイル(*.jkk)作成→提出ファイル作成、という流れです。

届書一覧入力画面から「資格取得」タブを選択し、「追加」ボタンを押すと入力画面が表示されます。


必要な項目を入力し、「登録」します。登録すると、項目がクリアされ、新規入力状態に戻ります。複数入力する必要がなければ、「入力終了」を押して画面を閉じます。(入力がクリアされたため、登録した内容がどうなったのか分からず、少し戸惑いました。)

一覧画面に戻ると、登録したデータが表示されています。


この画面から「提出ファイル作成」を選択すると、届書ファイルの保存を要求されます。届書ファイル保存後、提出ファイルを作成します。

公式プログラムが出力したファイルなので、中身に間違いはありません。
これまで同様、自社で開発したソフトでファイルを指定して申請し、無事に手続きを終えました。


またいつか、どこかで。

2022年4月11日月曜日

XAMLのお勉強メモ ④

 こんばんは。ざわです。

今回もXAML ネタです。よろしくお願いします。
これまでのXAMLメモはこちらになります。

動作環境

 ・Windows10

 ・Microsoft Visual Studio Community 2022 Preview 7.0

 ・Xamarin.Forms

今回試してみたこと

 少し前にマテリアルデザインの概念について学ぶ機会がありました。
 そこで、今回はXamarin Formsでマテリアルデザインを試してみようと思います。
 実装の流れとしては
  1. 「Xamarin.Forms.Visual.Material」NuGetパッケージをインストール
  2. マテリアルビジュアルを初期化
  3. マテリアルビジュアルを適用

 1. 「Xamarin.Forms.Visual.Material」NuGetパッケージをインストール

NuGetで「Xamarin.Forms.Visual.Material」で検索し、 
iOS および Android プラットフォームのプロジェクトにインストールします。

  

私の環境では、バージョン「5.0.0.2401」でインストールしようとするとエラーになりましたので、バージョンを下げて再度実行しました。

 


 2. マテリアルビジュアルを初期化

iOS 、Androidの各プラットフォームのプロジェクトで、Material Visualを初期化します。

iOSの場合 

AppDelegate.cs で、
Xamarin.Forms.Forms.Initメソッドの後に
Xamarin.Forms.FormsMaterial.Initメソッドを呼び出します。
global::Xamarin.Forms.Forms.Init();
global::Xamarin.Forms.FormsMaterial.Init();

 Androidの場合 

MainActivity.cs で、
Xamarin.Forms.Forms.Initメソッドの後に
Xamarin.Forms.FormsMaterial.Initメソッドを呼び出します。
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
global::Xamarin.Forms.FormsMaterial.Init(this, savedInstanceState);
 

 3. マテリアルビジュアルを適用

ここまで準備できたら、XAML側にマテリアルを適用します。

以下のコントロールが、マテリアルビジュアルがサポートされているコントロールなので、 

この中のいくつかを使って試してみます。


 ・ActivityIndicator

 ・Button

 ・CheckBox

 ・DatePicker

 ・Editor

 ・Entry

 ・Frame

 ・Picker

 ・ProgressBar

 ・Slider

 ・Stepper

 ・TimePicker

今回は「Button」「Entry」「DatePicker」「TimePicker」「Editor」「Slider」を使いました。 

ContentPage内のコントロールすべてに対して適用するため、
ContentPageに Visual="Material" を設定します。(特定のコントロールのみ設定することもできます)
マテリアルビジュアルを適用しない場合は Visual="Default" と設定します。

 
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="App4.MainPage"
             Visual="Material">

    <StackLayout BackgroundColor="#90caf9">
        <Label Text="タイトル:" Margin="20" />
        <Entry Placeholder="タイトル" x:Name="title" Margin="30, 0, 30, 10"/>

        <Label Text="日付:" Margin="20" />
        <DatePicker x:Name="datePicker"
        Format="D"
        Margin="30, 0, 30, 10" />

        <Label Text="時刻:" Margin="20" />
        <TimePicker x:Name="timePicker"
        Time="11:00:00"
        Format="T"
        Margin="30, 0, 30, 10" />

        <Label Text="メモ:" Margin="20" />
        <Editor x:Name="editor" Margin="30, 0, 30, 10" HeightRequest="80" />

        <Slider VerticalOptions="Fill" Margin="20" Maximum="360"/>

        <Button Text="登録" Margin="30, 0, 30, 10"/>
    </StackLayout>
</ContentPage>

 
実行結果
 左側が Material適用した画面で、右側が適用していない画面です。
 今回はAndroidでの確認のみで、iOSはまだ確認できていないのですが、、、
 Materialを適用した場合は、iOS と Android でほぼ同じ外観になっているはずです。

 
 これからはマテリアルデザイン、使っていきたいと思います。
 それではまた!

2022年4月1日金曜日

Typoraで作成した記事をブログにUPするまで

 

どうも。ひっくです。

今回はTyporaで作成した記事をブログにUPする方法をまとめます。

Typora関連記事

→第1回 はこちら Typora(Markdownエディタ)の紹介①

→第2回 はこちら Typora(Markdownエディタ)の紹介② ~画像の保存先を変更する~

→第3回 はこちら Typora(Markdownエディタ)の紹介③ ~数式を編集する~

→第4回 はこちら Typora(Markdownエディタ)の紹介④ ~シーケンス図を作成する~

→第5回 はこちら Typora(Markdownエディタ)の紹介⑤ ~フロー図を作成する~

→第6回 はこちら TyporaVer1.x リリースに伴い有料化(でもベータ版はまだまだ無料利用可能)

→第7回 はこちら Typora(Markdownエディタ)の紹介⑥ ~クラス図を作成する~

 

ブログUPまでの手順


これまで紹介したTyporaの記事を含め、ここ最近のブログ記事はTyporaを使用して作成しています。

手順としては以下の様な感じになります。

  1. Typora(Markdownエディタ)の紹介② ~画像の保存先を変更する~」に従い、

    画像の保存設定を変更する。(Typoraを最初に使う1回だけすればOK)

  2. 記事を書く(普段はここから)

  3. 記事で使用した画像をUpload

  4. 記事をHTML形式でコピー&ブログサービスへ貼り付け

  5. 記事の画像挿入先とUploadした画像URLを紐づけ

  6. (おまけ) 表紙画像を選定

 

画像の保存先設定を変更


Typora(Markdownエディタ)の紹介② ~画像の保存先を変更する~ 「保管先を変えてみよう」を参考に

設定を変更し、Typoraに貼付した画像が一つのフォルダに格納されるようにしておきます。

(「記事で使用した画像をUpload」する際に、記事ごとに画像がまとまっている方が楽なため)

 

記事を書く


好きなテーマで記事を書きます。

記事の先頭に以下の様にCSS定義を記載しておくと、CSSを使うことも可能になります。

  • CSS定義の例
  • 使用時(Typoraの表示上はCSS適用なしで「-」表示となりますが、CSSが有効になるとこう表示されます → )

記事で使用した画像をUpload


記事のMarkdownファイルと同じ階層にあるディレクトリ内に、記事で使用した画像が含まれています。

 

全て画像を選択する前に、不要な画像が含まれていないか確認してください。

(ver1.1以前では画像を貼付後、Typora上で削除してもソースとなる画像は削除されずに残るため。

Ver1.2以上のTyporaは、メニューから画像の削除でソースとなる画像も削除されるようです。)

以下では右から2番目・3番目の画像が不要なので削除します。

画像のUpload方法はそれぞれ使用されるブログサービスで確認してください。

 

---------------------------------------------

(参考)以下はBloggerで画像をUploadする方法です。

  1. 「画像を挿入」をクリック
  1. 「パソコンからアップロード」を選択

  2. ファイルを選択 → 画像を全選択 → 開く

  3. 選択クリック

  1. レイアウト選択 → OK

  2. Upload完了後

    ※これが記事の画像挿入先と画像を紐づける元ネタとなります。

     

記事をHTML形式でコピー&ブログサービスへ貼り付け


  1. 記事を全選択 → 編集 → HTMLとしてコピーを選択

  2. ブログサービスのエディタに貼り付け

 

記事の画像挿入先とUploadした画像URLを紐づけ


Typoraで画像を貼付した箇所は、HTML形式にすると以下の様に表示されています。

<p><img src="Typoraで作成した記事をブログにUPするまで.assets/image-20220328210335179.png" referrerpolicy="no-referrer" alt="image-20220328210335179"></p>

この部分をUploadした画像URLに置き換えます。置き換え方は次の通り。

 

  1. まず以下のタグを用意します。「画像URL」が置換場所になります。
<div class="separator" style="clear: both;"><a href="画像URL" style="display: block; padding: 1em 0px; text-align: center;"><img alt="" border="0" data-original-height="1152" data-original-width="2048" src="画像URL" width="600"></a></div>

  1. 続いてUpload後のURL情報を、見やすい形に整形します。

    エディタ(下記はサクラエディタ)に貼り付けて全て置換を選択すると

    こうなります。

  2. 最初のimgタグに画像のファイル名が記載されているので、対応するファイル名を取得します。

    「image-20220328210335179.png」で検索したら、以下URLが対応するものと分かりました。

  1. 「画像URL」をURL情報で置き換えたのが以下になります。

    「width="600"」が画像幅になるので、必要に応じて調整しましょう。

<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMMJq02vnRr7eMUSS2JLMvsjVuQyMIcrLyIA1NS7_l_kqgSL_4C-8j5mfR5kR-mCP3M3bTzVzkSGLDhhbR2KAVcq9oJy5GKY2Nl6lEjleuwHSgPZLXI5eJvdudPBnUTEeTtn-rBezOVjDc-TIe50D7dLfzu6XAw6lR-VCoqrjd0LfslZl09bSO3eE3KQ/s1600/image-20220328210335179.png" style="display: block; padding: 1em 0px; text-align: center;"><img alt="" border="0" data-original-height="1152" data-original-width="2048" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMMJq02vnRr7eMUSS2JLMvsjVuQyMIcrLyIA1NS7_l_kqgSL_4C-8j5mfR5kR-mCP3M3bTzVzkSGLDhhbR2KAVcq9oJy5GKY2Nl6lEjleuwHSgPZLXI5eJvdudPBnUTEeTtn-rBezOVjDc-TIe50D7dLfzu6XAw6lR-VCoqrjd0LfslZl09bSO3eE3KQ/s1600/image-20220328210335179.png" width="600"></a></div>

  • 置き換え前
  • 置き換え後

 

(おまけ)表紙画像を選定

ブログの先頭に表紙画像をつけておくと、目を引くことができるかと思います。

(記事と関連のある画像だとなお良し)

 

商用利用可・著作権フリーの画像を入手できる画像サイトから、ダウンロードして先頭に貼り付けておきましょう。

私は普段、次の画像サイトを良く利用しています。

写真AC

O-DAN(オーダン)

 

まとめ


Typoraで作成した記事をブログにUPする方法について、今回は紹介しました。

ブログを書き始めた頃、Bloggerのエディタと格闘していましたが、正直使い勝手が悪く

1記事書くのに結構時間がかかっていました。

Typoraに限らず、Markdownエディタなら記事を書くのに集中できるかと思います。

 

普段Markdownエディタを使ってブログを書かれている方には参考にならないかと思いますが、

これからブログを書き始めよう、もっと楽にブログを書きたいと思っている方は

是非参考にしてみてください。

 

今回はこのへんで。ではまた!

2022年3月26日土曜日

MaxBy & MinBy in .NET 6

どうも、もりもりです。

今回は.NET 6で追加されたLINQのMaxBy / MinByについてメモ。
.NET 6 より前ではどうしてた?代用できるメソッドはあるの?といったところもあります。

まずはMaxBy / MinBy (.NET 6)

こんなListがあったとして

new List<Person>()
{
    new Person(Name: "Ichiro", Age: 47),
    new Person("Jiro", 47),
    new Person("Saburo", 46),
    new Person("Siro", 41),
    new Person("Goro", 35),
    new Person("Rokuro", 35),
};

MaxBy、MinByを呼んでやると

var maxAgePerson = People.MaxBy(_ => _.Age);
Console.WriteLine($"\tMax : {maxAgePerson}");

var minAgePerson = People.MinBy(_ => _.Age);
Console.WriteLine($"\tMin : {minAgePerson}");

最大、最小の年齢に合致した最初の要素を返してくれます。 なんで今までなかったのか不思議ですが、ラクに取得できるようになったので嬉しいですね。

Max : Person { Name = Ichiro, Age = 47 }
Min : Person { Name = Goro, Age = 35 }

MaxとFirstの合わせ技 (.NET 5以前)

LINQでパッと思い付くのはこれでしょうか。Max()で値を取得して、その値を保持している最初の要素をFirst()で取得。

var maxAge = People.Max(_ => _.Age);
var maxAgePerson = People.FirstOrDefault(_ => _.Age == maxAge);
Console.WriteLine($"\tMax : {maxAgePerson}");

var minAge = People.Min(_ => _.Age);
var minAgePerson = People.FirstOrDefault(_ => _.Age == minAge);
Console.WriteLine($"\tMin : {minAgePerson}");

Aggregateで代用 (.NET 5以前)

集計処理をしてくれるAggregateを使用して実現できます。
xに大きい方の値を保持していき、各要素yとの比較を繰り返していきます。 今回はMaxBy/MinByに合わせて最初の要素を得るために「>=」としていますが、 最後の要素が欲しいということであれば「>」にすればOK。

var maxAgePerson = People.Aggregate((x, y) => x.Age >= y.Age ? x : y);
Console.WriteLine($"\tMax : {maxAgePerson}");

var minAgePerson = People.Aggregate((x, y) => x.Age <= y.Age ? x : y);
Console.WriteLine($"\tMin : {minAgePerson}");

拡張メソッド (.NET 5以前)

何度もAggregateを呼ぶことになるなら拡張メソッドを用意しておけばOK。

public static class LinqExtension
{
    public static T MinBy<T, U>(this IEnumerable<T> source, Func<T, U> func) where U : IComparable<U>
        => source.Aggregate((x, y) => func(x).CompareTo(func(y)) <= 0 ? x : y);

    public static T MaxBy<T, U>(this IEnumerable<T> source, Func<T, U> func) where U : IComparable<U>
        => source.Aggregate((x, y) => func(x).CompareTo(func(y)) >= 0 ? x : y);
}

呼び方は.NET 6のMaxBy()と全く同じように書けます。

var maxAgePerson = People.MaxBy(_ => _.Age);
Console.WriteLine($"\tMax : {maxAgePerson}");

var minAgePerson = People.MinBy(_ => _.Age);
Console.WriteLine($"\tMin : {minAgePerson}");

全体ソース

全体ソースを貼っておきます。 .NET 6 はmainメソッドを書く必要なくなりましたね。 .NET 5 以前のソースは言語バージョンによっては動かない書き方もしてますが、 そのままコピペしてvscodeのCode Runnerで実行できます。

.NET 6

Console.WriteLine($"Main() Start");

MaxBySample.Test1();

Console.WriteLine($"Main() End");

public record Person(string Name, int Age);

internal static class MaxBySample
{
    private static List<Person> People => new List<Person>()
    {
        new Person(Name: "Ichiro", Age: 47),
        new Person("Jiro", 47),
        new Person("Saburo", 46),
        new Person("Siro", 41),
        new Person("Goro", 35),
        new Person("Rokuro", 35),
    };

    public static void Test1()
    {
        Console.WriteLine($"*** MaxBy ***");

        var maxAgePerson = People.MaxBy(_ => _.Age);
        Console.WriteLine($"\tMax : {maxAgePerson}");
        
        var minAgePerson = People.MinBy(_ => _.Age);
        Console.WriteLine($"\tMin : {minAgePerson}");
    }
}

.NET 5 以前

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine($"Main() Start");

        MaxBySample.Test2();
        MaxBySample.Test3();
        MaxBySample.Test4();

        Console.WriteLine($"Main() End");
    }
}

public class Person
{
    public string Name {get; set;}
    public int Age {get; set;}

    public override string ToString()
        => $"Person {{ Name = {this.Name}, Age = {this.Age} }} ";
}

internal static class MaxBySample
{
    private static List<Person> People => new List<Person>()
    {
        new Person() {Name = "Ichiro", Age = 47},
        new Person() {Name = "Jiro", Age = 47},
        new Person() {Name = "Saburo", Age = 46},
        new Person() {Name = "Siro", Age = 41},
        new Person() {Name = "Goro", Age = 35},
        new Person() {Name = "Rokuro", Age = 35},
    };

    public static void Test2()
    {
        Console.WriteLine($"*** Max & First ***");

        var maxAge = People.Max(_ => _.Age);
        var maxAgePerson = People.FirstOrDefault(_ => _.Age == maxAge);
        Console.WriteLine($"\tMax : {maxAgePerson}");
        
        var minAge = People.Min(_ => _.Age);
        var minAgePerson = People.FirstOrDefault(_ => _.Age == minAge);
        Console.WriteLine($"\tMin : {minAgePerson}");
    }

    public static void Test3()
    {
        Console.WriteLine($"*** Aggregate ***");
        
        var maxAgePerson = People.Aggregate((x, y) => x.Age >= y.Age ? x : y);
        Console.WriteLine($"\tMax : {maxAgePerson}");

        var minAgePerson = People.Aggregate((x, y) => x.Age <= y.Age ? x : y);
        Console.WriteLine($"\tMin : {minAgePerson}");
    }

    public static void Test4()
    {
        Console.WriteLine($"*** MaxByExtention ***");
        
        var maxAgePerson = People.MaxBy(_ => _.Age);
        Console.WriteLine($"\tMax : {maxAgePerson}");

        var minAgePerson = People.MinBy(_ => _.Age);
        Console.WriteLine($"\tMin : {minAgePerson}");
    }
}

public static class LinqExtension
{
    public static T MinBy<T, U>(this IEnumerable<T> source, Func<T, U> func) where U : IComparable<U>
        => source.Aggregate((x, y) => func(x).CompareTo(func(y)) <= 0 ? x : y);

    public static T MaxBy<T, U>(this IEnumerable<T> source, Func<T, U> func) where U : IComparable<U>
        => source.Aggregate((x, y) => func(x).CompareTo(func(y)) >= 0 ? x : y);
}
以上、もりもりでした。