rksoftware

Visual Studio とか C# とかが好きです

Power Automate 条件を快適に設定する方法

Power Automate に限らずたいていのものはコードで管理することがベストプラクティスです。
条件も例外ではありません。

条件

■ 結論

右辺に全部書きます。

左辺に true と書いて右辺に真偽値を返す式を書きます。
これで、式ですべてを表現できるので非常に扱いやすく、見ても分かりやすくなります。
and や or を多段複合した条件も楽になります。ベリーグッド!

■ まず真っ先に知って欲しい

この設定方法。Power Automate 使いだした最初に教えてほしかった方法です。これから Power Automate を始めるすべての人にぜひ最初に知って欲しいです。

Power Automate アレイのフィルター処理を快適に設定する方法の余談 - 条件の場合

以前に Power Automate アレイのフィルター処理を快適に設定する方法 の記事を書きました。

この記事の内容、条件 にも使えるのでは? と思うかもしれません。私は発見したときにあの非常に設定が困難な 条件 でも使えたらかなりの生産性 UP ! と思い、急いで確認しに行きました。

■ 結論

■ 無念です。

条件には 詳細モードで設定 はありません。コードのプレビューもないので何か課題があるのかもしれません。無念です。

Power Automate アレイのフィルター処理を快適に設定する方法

Power Automate に限らずたいていのものはコードで管理することがベストプラクティスです。
アレイのフィルター処理も例外ではありません。

アレイのフィルター処理

■ 結論

[ 詳細設定モードで編集 ] をクリックします。
これだけで、アレイのフィルター処理が劇的に設定しやすくなります。

クリック後の様子


真偽値を返す式で設定できるようになりました。すばらしい!

■ 例 - 標準状態

例えば標準状態だとこんな感じに設定をします。ちょっと分かりにくいですよね。真ん中の枠は選択でコピペもできないところもつらいです。

この時のコードはこんな感じ。コードはシンプルなんですけれどもね。

{
    "inputs": {
        "from": "@outputs('複数の項目の取得')?['body/value']",
        "where": "@startsWith(item()?['Title'], 'title')"
    }
}

かなりのツラミ

この標準状態での入力は非常にツラミがあります。真ん中の枠がコピペできないのは先ほど書きましたが、そのほかにも。次の画像を見てください。

操作不能になっています。ツラミの画像です。どういう状況で画像のようになるかを説明します。

普通は、Power Automate の入力枠は式をメモ帳などに書いてそれをコピペして入力します。そうでない入力の仕方をしている方は少ないんじゃないかと思います。そして、アレイのフィルター処理で where の項目の左の枠にペーストすると画像のようになります。

■ 救世主 - 詳細モードで設定

詳細モードで設定すればそんなツラミともサヨナラです。式が直接書けます。

比較条件 (等しいや、より大きいなど) も式で見られるので非常に分かりやすいですね。式のまま表示されているのも、コードのプレビューを見るしたりコピーしてメモ帳などに貼り付けて確認などしなくて良いので非常に見やすいです。

■ まず真っ先に知って欲しい

この設定方法。Power Automate 使いだした最初に教えてほしかった方法です。これから Power Automate を始めるすべての人にぜひ最初に知って欲しいです。

C# 11 の新機能を確認「 ジェネリック型数値演算のサポート - 符号なし右シフト演算子 」

C# 11 の新機能を確認しています。目次は次の記事です。
rksoftware.hatenablog.com

今回は 「 ジェネリック型数値演算のサポート - 符号なし右シフト演算子 」。公式 Learn の記事は次です。
learn.microsoft.com

新しい右シフト演算子 >>> ができました。

■ 確認

int i= -1 >>> 1;

ちなみにこのコードは .NET 6 を指定した場合は次のエラーになります。

エラー CS8936 機能 '符号なし右シフト' は C# 10.0 では使用できません。言語バージョン 11.0 以上を使用してください。

■ 実行

実行結果は次のようになります。

int i= -1 >>> 1;
Console.WriteLine(Convert.ToString(i, toBase: 2).PadLeft(32, '0'));
//  01111111111111111111111111111111

■ 右シフト演算

これは結構マニアックな仕様なので、丁寧に基本のシフト演算から確認して行きましょう。

正の数をシフト演算

まずは正の数をシフト演算してみます。11 の位置が左右に移動 (シフト) しているのが分かります。

Console.WriteLine(Convert.ToString(3, toBase: 2).PadLeft(32, '0'));
Console.WriteLine(Convert.ToString(3 << 1, toBase: 2).PadLeft(32, '0'));
Console.WriteLine(Convert.ToString(3 >> 1, toBase: 2).PadLeft(32, '0'));
// 00000000000000000000000000000011
// 00000000000000000000000000000110
// 00000000000000000000000000000001

負の数をシフト演算

負の数をシフト演算すると不思議な感じに。左にシフトしたときには、右端に 0 が埋まったのに、右にシフトしたときには左端が 1 で埋まっています。

Console.WriteLine(Convert.ToString(-1, toBase: 2).PadLeft(32, '0'));
Console.WriteLine(Convert.ToString(-1 << 1, toBase: 2).PadLeft(32, '0'));
Console.WriteLine(Convert.ToString(-1 >> 1, toBase: 2).PadLeft(32, '0'));
// 11111111111111111111111111111111
// 11111111111111111111111111111110
// 11111111111111111111111111111111

ビットでなく、数値としてみると分かりやすいかもしれません。

Console.WriteLine(4 << 1);
Console.WriteLine(4 >> 1);
Console.WriteLine(-4 << 1);
Console.WriteLine(-4 >> 1);
//  8
//  2
// -8
// -2

■ 普通に 1 の位置がシフトして欲しい

そんな時に今回追加された >>> です。

Console.WriteLine(Convert.ToString(-1, toBase: 2).PadLeft(32, '0'));
Console.WriteLine(Convert.ToString(-1 << 1, toBase: 2).PadLeft(32, '0'));
Console.WriteLine(Convert.ToString(-1 >>> 1, toBase: 2).PadLeft(32, '0'));
// 11111111111111111111111111111111
// 11111111111111111111111111111110
// 01111111111111111111111111111111

■ これまではこうしていた

これまでは次のように uint にしていたようです。今回の >>> で便利になりましたね!

unchecked
{
    Console.WriteLine(Convert.ToString((uint)-1, toBase: 2).PadLeft(32, '0'));
    Console.WriteLine(Convert.ToString((uint)-1 << 1, toBase: 2).PadLeft(32, '0'));
    Console.WriteLine(Convert.ToString((uint)-1 >> 1, toBase: 2).PadLeft(32, '0'));
}
// 11111111111111111111111111111111
// 11111111111111111111111111111110
// 01111111111111111111111111111111

■ 覚えておきましょう

この機能は使わない人はほとんど使わない機能かもしれません。しかし >>> という演算子は非常に Web 検索が難しいのではないかと思います。出会ったときに検索しなくて済むように覚えておきましょう。

C# 11 の新機能を確認「 ジェネリック型数値演算のサポート - 緩和されたシフト演算子 」

C# 11 の新機能を確認しています。目次は次の記事です。
rksoftware.hatenablog.com

今回は 「 ジェネリック型数値演算のサポート - 緩和されたシフト演算子 」。公式 Learn の記事は次です。
learn.microsoft.com

シフト演算子のオーバーロードをする際に、右オペランド (第 2 引数) に int でない型を使えます。

■ 確認

次のようなコードが書けます。

Console.WriteLine(new Sample() >> new Dummy());  // Sample { }

record struct Dummy { }

record struct Sample
{
    public static Sample operator >>(Sample arg1, Dummy arg2) => new Sample();
}

ちなみにこのコードは .NET 6 を指定した場合は次のエラーになります。

エラー CS8936 機能 '緩和されたシフト演算子' は C# 10.0 では使用できません。言語バージョン 11.0 以上を使用してください。
record struct Dummy { }

record struct Sample
{
    public static Sample operator >>(Sample arg1, Dummy arg2) => new Sample();  // エラー CS8936 機能 '緩和されたシフト演算子' は C# 10.0 では使用できません。言語バージョン 11.0 以上を使用してください。
}

これまでは、int だけだったので、>> の右は intint に暗黙的な型変換のできる型しか書けませんでした。次のような感じです。

Console.WriteLine(4 >> 1);          // 2
Console.WriteLine(4 >> (short)1);   // 2
record struct Sample
{
    public static Sample operator >>(Sample arg1, int arg2) => new Sample();
}

■ どういうこと

次のように、数値計算した結果が int でなくとも右に書けるシフト演算が定義できます。

Console.WriteLine(new Sample() >> 1.0 / 2.0);

record struct Sample
{
    public static Sample operator >>(Sample arg1, int arg2) => new Sample();
    public static Sample operator >>(Sample arg1, double arg2) => new Sample();
}

これは、自分で算術演算を実装した型を使うときに利便を想定しているみたいです。具体例としては System.Numerics.INumber<TSelf> を実装した型などを想定しているようです。

Console.WriteLine(new Sample() >> new RNumber());

record struct Sample
{
    public static Sample operator >>(Sample arg1, RNumber arg2) => new Sample();
}

record struct RNumber : System.Numerics.INumber<RNumber>
{
    // 実装コード省略

今までは、シフト演算の右に独自の型を書くならば、暗黙的な型変換を実装する必要がありました。これからはその必要がなくなります。

Console.WriteLine(new Sample() >> new RNumber());

record struct Sample
{
    public static Sample operator >>(Sample arg1, int arg2) => new Sample();
}

record struct RNumber(int Value)
{
    public static implicit operator int(RNumber arg) => arg.Value;
}

■ 覚えておきましょう

この機能は使わない人はほとんど使わない機能かもしれません。しかし他者が書いたコードでオーバーフロー時の挙動が不審な場合に出会うかもしれません。そんな時思い出して対策が行えるように覚えておきましょう。

C# 11 の新機能を確認「 ジェネリック型数値演算のサポート - ユーザー定義の checked 演算子 」

C# 11 の新機能を確認しています。目次は次の記事です。
rksoftware.hatenablog.com

今回は 「 ジェネリック型数値演算のサポート - ユーザー定義の checked 演算子 」。公式 Learn の記事は次です。
learn.microsoft.com

演算子のオーバーロードをする際に、checked 用の演算子を定義できます。

■ 確認

次のようなコードが書けます。

record struct Record(int Value)
{
    public static Record operator +(Record arg1, Record arg2) => new(arg1.Value + arg2.Value);
    public static Record operator checked +(Record arg1, Record arg2) { checked { return new(arg1.Value + arg2.Value); } }
}

ちなみにこのコードは .NET 6 を指定した場合は次のエラーになります。

エラー CS8936 機能 'チェックされたユーザー定義演算子' は C# 10.0 では使用できません。言語バージョン 11.0 以上を使用してください。

■ 実行

実行してみるとこんな感じで確かにそれぞれの + 演算子が使われます。

Console.WriteLine(new Record(100) + new Record(200));               // Record { Value = 1 }
checked { Console.WriteLine(new Record(100) + new Record(200)); }   // Record { Value = 2 }

record struct Record(int Value)
{
    public static Record operator +(Record arg1, Record arg2) => new(1);
    public static Record operator checked +(Record arg1, Record arg2) { checked { return new(2); } }
}

■ checked の動作

checked の場合にオーバーフローを起こしてみましょう。例外がスローされます。

Console.WriteLine(new Record(int.MaxValue) + new Record(1));    // Record { Value = 1 }
try { checked { Console.WriteLine(new Record(int.MaxValue) + new Record(1)); } }
catch(Exception ex) { Console.WriteLine(ex.Message); }          // Arithmetic operation resulted in an overflow.

record struct Record(int Value)
{
    public static Record operator +(Record arg1, Record arg2) => new(arg1.Value + arg2.Value);
    public static Record operator checked +(Record arg1, Record arg2) { checked { return new(arg1.Value + arg2.Value); } }
}

今回は、intchecked 演算を行っているので、勝手に例外になってくれていますが、独自の計算をする場合は独自に例外をスローするようにしましょう。
※ オーバーフローで例外をスローしないなら checked 演算子にする必要がない

■ 覚えておきましょう

この機能は使わない人はほとんど使わない機能かもしれません。しかし他者が書いたコードでオーバーフロー時の挙動が不審な場合に出会うかもしれません。そんな時思い出して対策が行えるように覚えておきましょう。

C# 11 の新機能を確認「 ジェネリック型数値演算のサポート - インターフェイスの static virtual メンバー 」

C# 11 の新機能を確認しています。目次は次の記事です。
rksoftware.hatenablog.com

今回は 「 ジェネリック型数値演算のサポート - インターフェイスの static virtual メンバー 」。公式 Learn の記事は次です。

learn.microsoft.com

インターフェイスに static virtual メソッド、static abstract メソッドを定義できます。

■ 確認

次のようなコードが書けます。

interface IInterface
{
    static int Method1(int arg) => default;
    static virtual int Method2(int arg) => default;
    static abstract int Method3(int arg);
}

ちなみにこのコードは .NET 6 を指定した場合は次のエラーになります。

エラー CS8703 C# 10.0 では、修飾子 'virtual' はこの項目に対して有効ではありません。'11.0' 以上の言語バージョンをご使用ください。
エラー CS8703 C# 10.0 では、修飾子 'abstract' はこの項目に対して有効ではありません。'11.0' 以上の言語バージョンをご使用ください。
interface IInterface
{
    static int Method1(int arg) => default;
    static virtual int Method2(int arg) => default; // エラー CS8703 C# 10.0 では、修飾子 'virtual' はこの項目に対して有効ではありません。'11.0' 以上の言語バージョンをご使用ください。
    static abstract int Method3(int arg);           // エラー CS8703 C# 10.0 では、修飾子 'abstract' はこの項目に対して有効ではありません。'11.0' 以上の言語バージョンをご使用ください。
}

これらのメソッドを直接使おうとするとエラーになります。

IInterface.Method1(0);
IInterface.Method2(0);  // エラー CS8926 静的な仮想または抽象インターフェイス メンバーには、型パラメーターでのみアクセスできます。
IInterface.Method3(0);  // エラー CS8926 静的な仮想または抽象インターフェイス メンバーには、型パラメーターでのみアクセスできます。

interface IInterface
{
    static int Method1(int arg) => default;
    static virtual int Method2(int arg) => default;
    static abstract int Method3(int arg);
}

インターフェイスを実装する際、static abstract メソッドは実装する必要がありますが、static virtual メソッドは実装しなくても OK です。ただし、実装していないと呼び出せません。

IInterface.Method1(0);
CClass.Method2(0); // エラー CS0117 'CClass' に 'Method2' の定義がありません
CClass.Method3(0);

interface IInterface
{
    static int Method1(int arg) => default;
    static virtual int Method2(int arg) => default;
    static abstract int Method3(int arg);
}

class CClass : IInterface
{
    public static int Method3(int arg) => default;
}

static virtual メソッドも実装すれば呼び出せます。

IInterface.Method1(0);
CClass.Method2(0); // OK
CClass.Method3(0);

interface IInterface
{
    static int Method1(int arg) => default;
    static virtual int Method2(int arg) => default;
    static abstract int Method3(int arg);
}

class CClass : IInterface
{
    public static int Method2(int arg) => default;  // これがあると呼び出せる
    public static int Method3(int arg) => default;
}

■ ジェネリック インターフェイス

この機能はジェネリック インターフェイスで使うことを想定しているようです。こんな感じになるのですかね。

CClass.Method2(new CClass());
CClass.Method3(new CClass());

interface IInterface<TSelf> where TSelf: IInterface<TSelf>
{
    static virtual TSelf Method2(TSelf arg) => default;
    static abstract TSelf Method3(TSelf arg);
}

class CClass : IInterface<CClass>
{
    public static CClass Method2(CClass arg) => default;
    public static CClass Method3(CClass arg) => default;
}

演算子のオーバーロード

演算子のオーバーロードに使うことも想定しているようですね。C# では演算子のオーバーロードはあまりしない人が多いと思いますが、次のコードのような感じです。

var value = new CClass(1) + new CClass(2);
Console.WriteLine(value);   // CClass { Value = 3 }

interface IInterface<TSelf> where TSelf : IInterface<TSelf>
{
    static abstract TSelf operator +(TSelf arg1, TSelf arg2);
}

record struct CClass(int Value) : IInterface<CClass>
{
    public static CClass operator +(CClass arg1, CClass arg2) => new(arg1.Value + arg2.Value);
}

■ 覚えておきましょう

この機能は使わない人はほとんど使わない機能かもしれません。しかしライブラリが提供する型では使われることもあるでしょう。書けなくても覚えておかないと素晴らしいライブラリなど使いこなせなくなる日が来ると思います。覚えておきましょう。