読者です 読者をやめる 読者になる 読者になる

集中力なら売り切れたよ

プログラミングや、将棋などについて書きます。

C#の匿名メソッドとラムダ式の使い方を勉強しました

C#

以下のような判定処理を委譲するカウントメソッドを定義する。

static int Count(int[] numbers, Predicate<int> judge)
{
    int count = 0;
    foreach (int n in numbers) {
        if (judge(n)) {
            count++;
        }
    }
    return count;
}

C#2.0で追加された匿名メソッド、C#3.0で追加されたラムダ式を渡して実行する。

static void Main(string[] args)
{
    int[] numbers = System.Linq.Enumerable.Range(1, 40).ToArray();

    // 匿名メソッド(C# 2.0)
    // 後述するラムダ式のほうが簡潔に書けるので、
    // 互換性のためだけに残されている機能
    int count = Count(numbers, delegate(int n) { return n % 2 == 0; });
    Console.WriteLine(count); // => 20

    // ラムダ式(C# 3.0)を省略なしで書く
    count = Count(numbers, (int n) => { return n % 3 == 0; });
    Console.WriteLine(count); // => 13

    // ラムダ式の型と括弧とreturnは一つなら省略可能
    count = Count(numbers, n => n % 4 == 0);
    Console.WriteLine(count); // => 10
}

Rubyでyieldで処理を委譲したり、メソッドにブロックを渡す感覚とほぼ同じだとわかりました。

0から15までの数値を16進数、2進数で表示するプログラム

C# Ruby

Rubyで書くと標準のprintfの指定方法に2進数が備わっているので簡単です。

(0..15).each do |i|
  printf("0x%02x = %04b\n", i, i)
end

C#ではConsole.WriteLineの書式では16進数は可能ですが、2進数には変換できないのでConvertクラスを利用して一旦変換してから呼び出します。

using System;

class Program
{
    static void Main(string[] args)
    {
        for (int i = 0; i < 16; i++) {
            string b = Convert.ToString(i, 2);
            int n = Convert.ToInt32(b);
            Console.WriteLine("0x{0:x2} = {1:D4}", i, n);
        }
    }
}

出力結果

基本情報技術者試験などでは基数変換問題で16進数から2進数に変換する問題は頻出なので0から15は丸暗記するくらいでもいいと思います。

0x00 = 0000
0x01 = 0001
0x02 = 0010
0x03 = 0011
0x04 = 0100
0x05 = 0101
0x06 = 0110
0x07 = 0111
0x08 = 1000
0x09 = 1001
0x0a = 1010
0x0b = 1011
0x0c = 1100
0x0d = 1101
0x0e = 1110
0x0f = 1111

C言語で数値のべき乗を求めるにはpow関数を使う

C++

標準ライブラリのpow関数を使うとべき乗を求めることができます。

#include <stdio.h>
#include <math.h>

int main(int argc, char* argv[])
{
    for (double i = 0; i < 32; i++) {
        printf("2 ** %d = %d\n", (int) i, (int) pow(2.0, i));
    }
    return 0;
}

しかしコンパイルして実行してみるとわかりますが2 ** 31で桁あふれしてしまいます。

C言語は難しいですね。

実行結果

2 ** 0 = 1
2 ** 1 = 2
2 ** 2 = 4
2 ** 3 = 8
2 ** 4 = 16
2 ** 5 = 32
2 ** 6 = 64
2 ** 7 = 128
2 ** 8 = 256
2 ** 9 = 512
2 ** 10 = 1024
2 ** 11 = 2048
2 ** 12 = 4096
2 ** 13 = 8192
2 ** 14 = 16384
2 ** 15 = 32768
2 ** 16 = 65536
2 ** 17 = 131072
2 ** 18 = 262144
2 ** 19 = 524288
2 ** 20 = 1048576
2 ** 21 = 2097152
2 ** 22 = 4194304
2 ** 23 = 8388608
2 ** 24 = 16777216
2 ** 25 = 33554432
2 ** 26 = 67108864
2 ** 27 = 134217728
2 ** 28 = 268435456
2 ** 29 = 536870912
2 ** 30 = 1073741824
2 ** 31 = -2147483648

RubyとC#のLINQとの比較、3の倍数を抜き出すプログラム

C# Ruby

3の倍数と3のつく数字のときオモロー!というプログラム(FizzBuzz問題系)

Rubyで書くと非常に楽です(自分が慣れているからでもありますが)。

# coding: cp932
result = (1..40).select do |i|
  i % 3 == 0 || i.to_s.include?("3")
end
for i in result
  puts "#{i}:オモロー!"
end

C#LINQやクエリ構文の使い方を調べて書くと似たような書き方ができました。データ型はvarで宣言しても問題なくコンパイルできるんですが、まだC#に慣れてないのでちゃんと型宣言しようと思います。

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

public class Program
{
    public static void Main(string[] args)
    {
        IEnumerable<int> result = Enumerable.Range(1, 40)
            .Where(n => n % 3 == 0 || n.ToString().Contains("3"));
        foreach (int i in result) {
            Console.WriteLine("{0}:オモロー!", i);
        }
    }
}

実行結果

3:オモロー!
6:オモロー!
9:オモロー!
12:オモロー!
13:オモロー!
15:オモロー!
(以下略)

C#やPowerShellでOSのバージョンを確認する方法

C# PowerShell

C#ではSystem.Environment.OSVersionで取得できます。

using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(Environment.OSVersion);
        }
    }
}

PowerShellでも同様です。

PS C:\Users\Ryo> Write-Host ([System.Environment]::OSVersion)
Microsoft Windows NT 10.0.14393.0