狐好きぷろぐらまー

狐好きプログラマーのブログです。

C#初心者がDartとC#のコードを比較してみた【その4】

こんにちは。 pregum_foxです。

このDartC#の比較も、その4まで続きましたがこの回で一通りは終わりそうです。

思ったより長くて大変でしたが、比較してみた方が個人的には理解が早くなったと思います。
比較を放棄した項目もありますが

C#Dartも更新速度が速いため、ぼけ~っとしていると置いてけぼりを食らうので最新情報を随時確認したいと思います。

これが書き終わったら、次はFlutterについて書いていきたいと思います。
もちろんC#についても書いていきたいと思います。
昔の自分が書いた物を思い出すのは大変ですが

以前の記事は以下のURLから飛べます。

pregum-fox.hatenablog.jp

pregum-fox.hatenablog.jp

pregum-fox.hatenablog.jp

それでは残りの項目を書いていきたいと思います。

目次です

動作環境

言語 動作環境
Dart 2.4.0
C#/. Net Core C#7.2 / . Net Core 2.1

呼び出し可能クラス

Dartでは、クラス内のメソッドでcallメソッドを実装すれば、インスタンスを関数のように呼び出せるようになります。

void main(List<String> args) {
  var cc = CallableClass();
  // クラス変数名()でcallメソッドが呼ばれる。
  var out = cc('hello', c: 3, b: 4);
  assert(out == 'a: hello, b + c: 7!');
}

class CallableClass {
  // callメソッドを実装
  String call(String a, {int b, int c}) => 'a: $a, b + c: ${b + c}!';
}
using System;
using static System.Diagnostics.Debug;

class Program
{
    static void Main(string[] args)
    {
        var cc = new Func<string, int, int, string>(
            (string a, int b, int c) => $"a: {a}, b + c: {b + c}!");

        var @out = cc("hello", 4, 3);
        Assert(@out == "a: hello, b + c: 7!");

        // ネタですが、インデクサでもいけます。
        var cc2 = new CallableClass();
        var out2 = cc2["hello", 4, 3];
        Assert(out2 == @out);
    }
}

class CallableClass
{
    // インデクサ(普通はこんな使い方はしません)
    public string this[string a, int b, int c]
    {
        get { return $"a: {a}, b + c: {b + c}!"; }
    }
}

Dartのみ】Isolate

IsolateとはDartが実行されるスレッドの事を指します。
C++とかの多くの言語では複数のスレッドで同じメモリを共有しますが、
Dartは、各スレッドはメモリも別々に持っていて、独立して動きます。

下記のサイトから引用しました。

FlutterでIsolateを用いた並列処理をするべきシーンとそのやり方 - Flutter 🇯🇵 - Medium

Main Isolateだけでは Futures・Streams APIなどを用いて並行処理はできるが並列処理はできない
ネットワーク通信のレスポンス待ちなどのCPU負荷が低く単に長い待ち時間が発生するだけの処理は、単にMain Isolate上での並行処理で済ませるだけで良い
16ms(60fps端末の場合)を超える処理時間を要するようなCPU負荷の特に高い処理をUIのフレームレートを落とさずに行うには、別のIsolateを起動して並列処理する必要がある

以下のサンプルはこちらのサイトから引用しました。

Dartのアイソレート間で相互通信をする例 - Qiita

今は理解力が足りないので、いつかちゃんと理解したいです。。。

import 'dart:isolate';
import "dart:async";

main() async {
  try {
    var channel = new ReceivePort();
    await Isolate.spawn(echo, channel.sendPort);

    StreamIterator itr = new StreamIterator(channel);
    if (await itr.moveNext()) {
       SendPort callbackSendPort = itr.current;
       while (await itr.moveNext()) {
         print('main: received ${itr.current}');
         callbackSendPort.send('hoy!');
       }
    }
  } catch (e) {
    print('error ${e}');
  }
}

// the entry point for the isolate
Future echo(sendPort) async {

  var callBackReceivePort = new ReceivePort();
  sendPort.send(callBackReceivePort.sendPort);
  callBackReceivePort.listen((msg){
    print('echo: received ${msg}');
  });
  while (true) {
    await new Future.delayed(new Duration(seconds: 1));
    sendPort.send("hello");
  }
}

Typedefs

typedefを使用することによって、型のエイリアスを設定することができます。
Dartの方もジェネリクスのtypedefに対応しているようです。

main() {
  var coll = SortedCollection(sort);
  assert(coll.compare is int Function(Object a, Object b));
  assert(coll.compare is Compare);
  assert(coll.function is Function);
  // 戻り値が違う為is!でtrueを返す。
  assert(coll.function is! StringCompare);
}

int sort(Object a, Object b) => 0;

typedef Compare = int Function(Object a, Object b);

typedef StringCompare = String Function(Object a, Object b);

class SortedCollection{
  Function function;
  Compare compare;

  SortedCollection(int f(Object a, Object b)) {
    function = f;
    compare = f;
  }
}
using System;
using static System.Diagnostics.Debug;

using Compare = System.Func<object, object, int>;
using StringCompare = System.Func<object, object, string>;

class Program
{
    static void Main(string[] args)
    {
        var coll = new SortedCollection(sort);
        Assert(coll.compare is Func<object, object, int>);
        Assert(coll.compare is Compare);
        Assert(coll.function is Func<object, object, int>);
        // 戻り値がstringで合わないので一致しない
        Assert(!(coll.function is StringCompare));
    }

    public static int sort(object a, object b) => 0;
}

class SortedCollection
{
    public Func<object, object, int> function;
    public Compare compare;

    public SortedCollection(Func<object, object, int> f)
    {
        function = f;
        compare = f;
    }
}

メタデータ

@Javaアノテーションの書き方でメタデータをします。
付与できるオブジェクトはライブラリ、クラス、typedef、型パラメータ、コンストラクタ、ファクトリコンストラクタ、関数、フィールド、パラメータ、変数宣言の前およびインポートまたはエクスポートディレクティブの前に表示できます。
リフレクションを使用して実行時にメタデータを取得できます。

C#メタデータに当てはまるものは属性ですね。

main() {
  doSomething();
}

class Todo {
  final String who;
  final String what;

  const Todo(this.who, this.what);
}

@Todo('pregum', 'something')
void doSomething() {
  print('do something.');
}
using System;
using static System.Diagnostics.Debug;

class Program
{
    static void Main(string[] args)
    {
        DoSomething();
    }

    [Todo("pregum", "something")]
    static void DoSomething()
    {
        WriteLine("do something.");
    }
}

[System.AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
sealed class TodoAttribute : Attribute
{
    readonly string who;
    readonly string what;

    public TodoAttribute(string who, string what)
    {
        this.who = who;
        this.what = what;
    }

    public string Who => who;
    public string What => what;
}

コメント

コメントはDartC#もほぼ同じです。

1行コメント
main() {
  // doSomething();
  // コメント
}
class Program
{
    static void Main(string[] args)
    {
        // DoSomething();
        // コメント
    }
}
複数行コメント
main() {
  /* ここから

  
  ここまでコメント */
}
class Program
{
    static void Main(string[] args)
    {
        /*`ここから


        ここまでコメント */
    }
}
ドキュメントコメント
main() {

}

/// 挨拶をする関数です。
/// [name] に挨拶をする対象の人の名前を入れてください。
void Greeting(String name){
  print('hi! $name');
}
class Program
{
    static void Main(string[] args)
    {
    }

    /// <summary>
    /// 挨拶をする関数です。
    /// </summary>
    /// <param name="name"> 挨拶をする対象の人の名前 </param>
    static void Greeting(string name)
    {

    }
}

雑感

最後になるほど、質が落ちて行っているのが目に見えてわかりました。。。
ただ、Dartについて一通り知ることができたので、FlutterではDartの書き方でハマることはほとんどないかなと思います。
Isolateや非同期ジェネレータやStream辺りは、実際に使ってみないとわからない所だらけなので、Flutterでサンプルアプリを作りながら学習していく予定です。

後は、Dartのテストコードの書き方などがあるのでそれも調べてみたいと思います。

ここまで読んで頂きありがとうございました。

参考サイト