20210117のC#に関する記事は6件です。

Hello Xamarin!

はじめに

こんにちは。初めてQiitaを書きます。ドッキドキです。
よろしくお願いします。

2020年に新卒で入社した会社でC#とWPFを使ってぼちぼちやっています。

前々から気になっていたXamarinを使ってみたので自分のアウトプットの場として記事を書こうと思った次第です。

作ったもの

今回はお試しということで、簡単な四則演算アプリを作りました。

スクリーンショット 2021-01-17 19.54.11.png

スクリーンショット 2021-01-17 23.10.42.png

数字を入力、演算子を選択して計算ボタンを押すと答えが出力されるだけのものになります。

コード

Xaml

MainPage.xaml
<?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="test1.MainPage">

    <StackLayout Orientation="Vertical" Margin="30,50,0,0">
        <StackLayout Orientation="Horizontal">
            <Entry x:Name="left" WidthRequest="100" VerticalOptions="Start"/>
            <Picker x:Name="picker"/>
            <Entry x:Name="right" WidthRequest="100" VerticalOptions="Start" />
            <Label Text="="/>
            <Label x:Name="answer" WidthRequest="100" />
        </StackLayout>
        <Button x:Name="button" Text="計算" Clicked="OnButtonClicked"/>
    </StackLayout> 

</ContentPage>

C#

MainPage.Xaml.cs
using System;
using Xamarin.Forms;

namespace test1
{
    public partial class MainPage : ContentPage
    {
        static string[] operators = new[] { "+", "-", "×", "÷" };

        public MainPage()
        {
            InitializeComponent();
            // pickerに演算子をセット
            picker.ItemsSource = operators;
            // 初期値は"+"
            picker.SelectedIndex = 0;
        }

        void OnButtonClicked(object sender, EventArgs e)
        {
            var leftNumberText = left.Text;
            var rightNumberText = right.Text;
            if (double.TryParse(leftNumberText, out var leftNumber) &&
                double.TryParse(rightNumberText, out var rightNumber)){
                var answer = Calculate(leftNumber, rightNumber, picker.SelectedItem.ToString());
                this.answer.Text = answer.ToString();
            }
        }

        static double Calculate(double leftNumber, double rightNumber, string ope)
        {
            switch (ope)
            {
                case "+":
                    return leftNumber + rightNumber;
                case "-":
                    return leftNumber - rightNumber;
                case "×":
                    return leftNumber * rightNumber;
                case "÷":
                    if (rightNumber == 0) {
                        throw new InvalidOperationException();
                    } else {
                        return leftNumber / rightNumber;
                    }

                default:
                    throw new InvalidOperationException();
            }
        }
    }
}

ただボタンのイベントハンドラで計算してるだけですね。
WPFとのコントロールの違いに少し戸惑いました。

お試しなので、コードの内容については(例外処理とか)多めに見てくださいということで。

マシンが非力なせいか、Xamarinだから仕方ないのかエミュレーターの起動が遅くてイライラしますね。

夏のボーナスでたら新しいMac買おうかな。。。

今回はコードビハインドでやりましたが、次はViewModel作ってMVVMで四則演算したいと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

C#のコーディングルールをまとめてみました。

udemyの動画を視聴してアウトプットをかねて学んだことをまとめてみました。
駆け出しのエンジニアで、実力はまだまだですか記事を書いてみました:runner_tone3:

今回は「C#のコーディングルール:スタイルコップアナライザーを使ってチーム全員が同じコードを書く方法」という動画をみてアウトプットを行いました。

1、「コーディングにおける名前付のルール」

・命名は英語でつける。
・基本的にはPascal型で書く。Pascalとは、頭文字は大文字で書くという意味。
(二句の英単語ならUserNameと言うように格句を大文字にして書く。)

・プロジェクト名は、例えば製品名のようにアイテムの名前を記載。
 名称:(ex:ps4)

・ソリューション名はアイテム名.用法というように記載。
 用法:(ex:ps4.説明書)

・二文字の略語は大文字にする。
IE (ex:Internet Explorer)

・三文字の略語の場合は先頭だけ大文字にする。
 Sql(Structured Query Language)

・例外(2つのみ)
・identifier →id
・Okay →Ok

2.「名前空間の決め方」
会社名+製品名+プロジェクト名+フォルダ名

・ローカルルール(マイクロソフトで規定されていない物)
 →チームで統一されてれば良いルール。

・動画内で推奨されていたルール。
private変数はアンダーバーをつける。
(ex:_userName)
→thisの代わりにアンダーバーをつけると表示がわかりやすい。。

・コントロール名の名付け方
最後にコントロール名をつける。
ボタンの時:SaveButton
テキストボックスの時:ProductNameTextBox

・クラス名・ファイル名の付け方。

語尾に種類をつける。
ex)ProductListForm

3.「StyleCop.Analyzersの使い方」

StyleCop.Analyzersとは、VS上で使用する
コーディングルールの誤りを警告する拡張ツール。

・警告が番号でエラーウィンドウに出る、
(ex:SA--)

・不要なルールと感じれば、該当警告の部分を選択し非表示にする、

・class作ったらxmlコメントとアクセス修飾を記載する。

・if文等で中括弧{}を使用した際、もう一度使う際は一行開けて次の中括弧を使用する。

・メソッドの中にコメントは避ける。どうしても描きたい際はスラッシュは4つ書く。。

・「アクセスレベルの順番」
 public→internal→protected internal→protected→private
 の順番で記載する。

以上で学んだことのまとめを終わります。
今回初めてのQiita執筆となりました。
これからも継続的にアウトプットかねてエンジニアとしてより高みを目指していきたいと思います。

もしよろしければ励みになりますため、LGTMをお願いします:sunny:

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Unity】カメラの揺らし方

方法

揺れるという動きを「視点が球内部のランダムな点に移動し続けた後、元の視点に戻る」という風に解釈します。掴みにくい方は以下の動画の立方体を追ってみてください。球内部の点にランダムで移動しているだけですが、立方体に注視することで目が回るような感覚に陥ると思います。

実装

実装はシンプルで以下のコードになります。

CameraShake.cs
using System.Collections;
using UnityEngine;

public class CameraShake : MonoBehaviour
{
    public IEnumerator Shake(float duration, float magnitude)
    {
        Vector3 originalPosition = transform.position;
        float elapsed = 0f;

        while (elapsed < duration)
        {
            transform.position = originalPosition + Random.insideUnitSphere * magnitude;
            elapsed += Time.deltaTime;
            yield return null;
        }
        transform.position = originalPosition;
    }
}

球の半径とカメラが揺れる時間を引数に渡して使用します。

transform.position = originalPosition + Random.insideUnitSphere * magnitude;

Random.insideUnitSphereとは半径1の球体の内部の点をランダムに返すメソッドになります。半径 = 1 * magnitudeとすることで、揺れの大きさを決定しています。

elapsed += Time.deltaTime;

ランダムに位置を変更する毎の時間をelapsedに追加しておき、指定時間を超えるまで処理を続けます。

使用方法

以下のように呼び出して使用します。

StartCoroutine(cameraShake.Shake(0.3f, 0.6f));

使用用途に合わせて、揺れの大きさや、揺れ時間を変更するとGOOD!

実装動画

 終わりに

  • 注意点として、Canvas内部は揺れません。UIや背景等も揺らしたい場合は、Canvasから外しましょう。
  • 一回作成しておくと、使い回しのきく便利なプログラムになると思います。是非参考にしてみてください。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

TwitterAPIトレンドをツイート Ver.C#

Image1.jpg

Program.cs
using System;
using System.Collections.Generic;
using System.Threading;
using Newtonsoft.Json;

namespace ConsoleApp1
{
    public class Trend
    {
        public string name { get; set; }
        public string url { get; set; }
        public object promoted_content { get; set; }
        public string query { get; set; }
        public int? tweet_volume { get; set; }
    }

    public class Location
    {
        public string name { get; set; }
        public int woeid { get; set; }
    }

    public class JsonData
    {
        public List<Trend> trends { get; set; }
        public DateTime as_of { get; set; }
        public DateTime created_at { get; set; }
        public List<Location> locations { get; set; }
    }

    public class Root
    {
        public List<JsonData> json_data { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            //API key
            string apiKey = "<APIキー>";
            //API secret key
            string apiSecretKey = "<APIシークレットキー>";
            //Access token
            string accessToken = "<アクセストークン>";
            //Access token secret
            string accessTokenSecret = "<アクセストークンシークレット>";

            //認証情報
            var tokens = CoreTweet.Tokens.Create(apiKey, apiSecretKey, accessToken, accessTokenSecret);
            //大阪のトレンド情報取得
            var TrendsJson = tokens.Trends.Place(15015370); //Osaka

            //JSONデータを取得
            string JsonData = TrendsJson.Json.ToString();
            //うまくデシリアライズできないので、ちょとデータ加工。。
            JsonData = "{ json_data: " + JsonData + "}";

            //URLデコードする
            string UrlDec = System.Web.HttpUtility.UrlDecode(JsonData);
            //JSON文字列をデシリアライズ
            Root TrendData = JsonConvert.DeserializeObject<Root>(UrlDec);

            //練習数
            int DataCnt = 3;

            //ツイート
            tokens.Statuses.Update(status => DataCnt + "単語のフリック練習スタート!?");
            //1秒待つ
            Thread.Sleep(1000);

            for (int idx = 0; idx < DataCnt; idx++)
            {
                //取得トレンド総数
                int TrendCnt = TrendData.json_data[0].trends.Count;

                //ランダム数値生成
                Random Rnd = new Random();
                int TrendRdm = Rnd.Next(0, TrendCnt);

                //トレンド文字列取得
                string TrendText = TrendData.json_data[0].trends[TrendRdm].query;
                //#はいらないので置換
                TrendText = TrendText.Replace("#","");

                //ツイート
                tokens.Statuses.Update(status => "【" + (idx + 1) + "】" + TrendText);
                //1秒待つ
                Thread.Sleep(1000);
            }

            //ツイート
            tokens.Statuses.Update(status => "終了?");
        }
    }
}

Follow @miki1220jp
↑よろしくお願いします:bow:ぜひぜひ

▼ 参考リンク!ありがとうございます:blush:
https://developer.twitter.com/en/docs/twitter-api/v1/trends/trends-for-location/api-reference/get-trends-place - TwitterAPIトレンドのリファレンス
https://qiita.com/hogeta_/items/8e3224c4960e19b7a33a - WOEID一覧
https://json2csharp.com/json-to-csharp - JSON文字列をC#のクラスにしてくれる

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

C#にpythonで作った処理を組み込む【pythonnet準備+確認編 2021年1月最新】

概要

pythonで作った処理(主にはtensorflow, pytorch等のディープラーニング系)をGUIから動かして結果を表示したいということがあると思います。
PyQtでもいけるかもなんですが、C#を扱える人の方が周りに多いので組み込むことができると嬉しいと思い調べたところ、
以下の先人の方々が使い方をまとめていただいていますのでそれを元に実際にtensorflowで作ったモデルを使ってアプリを作るところまでの手順を記事したいと思います。
本記事はまずは準備と動作確認編です。
2021年1月現在、pythonnet自体のソースコードの更新がありますので最新の手順を載せます
C#初心者なので間違っているところもあるかもしれませんがあしからずご了承ください・・・

参考①:.NET (C#)からpythonを呼び出す
参考②:Pythonnetを使って.NetからPythonコードを実行してみました(Hallo World編)

0.前提

開発の環境
visualstudio2019 community Version 16.7.7
NuGet パッケージ マネージャー 5.7.0
Anaconda Navigator 1.9.12

C#の環境
.NET Framework 4.7.2

pythonの環境
Python 3.7.6
tensorflow 2.3.0
numpy 1.18.5

前提知識
・pythonでpip等で環境構築ができ、コーディングできる人
・C#が少しわかる人

1.pythonnetの導入

Nugetで導入

python3.7であればNugetを使って簡単に導入できます(2021/01/10現在)
画面④.png
 ⇒2.呼び出して使うまで飛ばしてください

自分でビルドして導入

以下の記事を参考にさせていただきました。
pythonnetの古いソースコードであれば以下の記事を参考にしていただければと思います。

参考:.NET (C#)からpythonを呼び出す
参考:Pythonnetを使って.NetからPythonコードを実行してみました(Hallo World編)

2021年1月10日現在の最新のソースコードでのビルド方法をここでは記述します。

1.pythonnetのgithubリポジトリから最新コードをcloneし、pythonnet.slnを開く
2.プロジェクトPython.Runtimeのプロジェクト プロパティを開き、コンパイルシンボルを手入力する。
 python3.8を使いたい場合はPYTHON38;WINDOWSと入力。3.7の場合はPYTHON38を37に変更してください。
画面①.png
 ちなみにruntime.csの中身を見るとコンパイルシンボルの設定の方法がわかるようになっています。
 WINDOWSを入力していないとdllの中身がpython38となり、実際に使うときにはpython3.8を探しに行くのでうまくdllを読み込めなくなります。
画面②.png

3.ソリューションエクスプローラーのPython.Runtimeで右クリックしてビルドを選択する

うまくビルドが通るとルートフォルダの
src\runtime\bin\Debug\netstandard2.0

Python.Runtime.dll
が生成されていると思います。

2.C#からpythonnetを呼び出して使ってみる

参考:.NET (C#)からpythonを呼び出す
先人の方のコードの書き方をほぼ真似するだけですが、フォームにラベルを配置してnumpyのバージョン表示、numpyでの簡単な計算をするアプリを作ってみようと思います。

1.フォームのソリューションを作る

画面③.png
画面④.png

2.プラットホームの変更

画面⑤.png
画面⑥.png
画面⑦.png

プラットホームがx64になっていることを確認してください。
image.png

3.参照の追加

先ほど作成したDLLファイルを参照します
画面⑧.png画面⑨.png
image.png

Python.Runtimeが追加されていることを確認してください。
画面⑩.png

4.サンプルコード作成

こんな感じでフォームを作ってください。
image.png

参考:.NET (C#)からpythonを呼び出す
後は先人の方のコードを参考に書くだけです。

Form.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Runtime.InteropServices;

using Python.Runtime;

namespace pythonnet_numpy_version
{
    public partial class Form1 : Form
    {
        /// <summary>
        /// pythonライブラリを共有して使うための変数
        /// </summary>
        public dynamic np;
        public Form1()
        {
            InitializeComponent();
        }

        /// <summary>
        /// プロセスの環境変数PATHに、指定されたディレクトリを追加する(パスを通す)。
        /// </summary>
        /// <param name="paths">PATHに追加するディレクトリ。</param>
        public static void AddEnvPath(params string[] paths)
        {
            var envPaths = Environment.GetEnvironmentVariable("PATH").Split(Path.PathSeparator).ToList();
            foreach (var path in paths)
            {
                if (path.Length > 0 && !envPaths.Contains(path))
                {
                    envPaths.Insert(0, path);
                }
            }
            Environment.SetEnvironmentVariable("PATH", string.Join(Path.PathSeparator.ToString(), envPaths), EnvironmentVariableTarget.Process);
        }
        // フォームが呼び出されるときに処理させる
        private void Form1_Load(object sender, EventArgs e)
        {
            // *-------------------------------------------------------*
            // * python環境の設定
            // *-------------------------------------------------------*

            // python環境にパスを通す
            // TODO: 環境に合わせてパスを直すこと
            var PYTHON_HOME = Environment.ExpandEnvironmentVariables(@@"%userprofile%\Anaconda3\envs\tensorflow-2-3-0");
            // pythonnetが、python本体のDLLおよび依存DLLを見つけられるようにする
            AddEnvPath(
              PYTHON_HOME,
              Path.Combine(PYTHON_HOME, @"Library\bin")
            );

            // python環境に、PYTHON_HOME(標準pythonライブラリの場所)を設定
            PythonEngine.PythonHome = PYTHON_HOME;

            // pythonの処理をする=numpyの定義とバージョンをラベルに表示させる
            using (Py.GIL())
            {
                // numpyのインポート
                np = Py.Import("numpy");
                // numpyのバージョンを変数に格納
                dynamic np_version = np.__version__;
                // string型にして文字列と連結させラベルに表示
                labelNumpyVersion.Text = "numpyバージョン:" + np_version.ToString();
            }
        }
        // ボタンをクリックするとnumpyのメソッドを使って簡単な計算をしてラベルに表示
        private void buttonCalc_Click(object sender, EventArgs e)
        {
            // 簡単な計算をして変数に格納
            dynamic result = np.cos(np.pi / 3);
            // ToStringしなくても文字列にくっつけると勝手に型を変えてくれる
            labelResult.Text = "np.cos(np.pi / 3)=" + result;
        }
    }
}

基本は参考にしている記事の通りに書くだけですが、1つポイントとしてフォームアプリの場合は色々なコントロールでnumpyを使いたいのでインポートしたときに格納するメンバー変数を定義しておく必要があります。
まとめると以下の通りになります。(使い方によってはアクセス修飾子の適切な設定はあるかもです・・・とりあえずpublicにしときました)

メンバー変数の定義

hogehoge.cs
    public partial class Form1 : Form
    {
        /// <summary>
        /// pythonライブラリを共有して使うための変数
        /// </summary>
        public dynamic np;

numpyの定義

hogehoge.cs
            // pythonの処理をする=numpyの定義とバージョンをラベルに表示させる
            using (Py.GIL())
            {
                // numpyのインポート
                np = Py.Import("numpy");

numpyの使用

hogehoge.cs
            // 簡単な計算をして変数に格納
            dynamic result = np.cos(np.pi / 3);

3.終わりに

pythonからプログラミングを始めた俄かでC#を勉強してまだ数ヶ月でpythonnetをビルドするところで半日くらいかかってしまい心が折れそうでしたが何とか形できてホッとしています。

次はtensorflowとopencvを使ってC#側で画像を読み込んでpythonでセグメンテーションのモデルで推論した結果をC#のpictureboxに表示するアプリを作る記事を書こうと思います。

以上です。
不明点、おかしい点ありましたらコメントよろしくお願いします。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【C#】調査用の実行時間計測クラス

背景

レスポンスチューニングをする際に、
まず調査として各処理にどれくらいの実行時間がかかっているのか知りたいという場面がある。
その際に、ソースコードに簡単に仕込めて実行時間を計測できる仕組みがあればと思い作ってみました。

作ったものとその動作

とりあえず作ってみたものがこれ

コード

public class TimeMeasure
{
    //Property
    private Dictionary<string, TimeRecordItem> TimeRecordDic { get; set; }
    private string ClassName { get; set; }
    //Public Method
    public void Record(string key = null, string suffix = "")
    {
        if (key == null) key = new System.Diagnostics.StackFrame(1).GetMethod().Name;
        if (!string.IsNullOrEmpty(suffix)) key = string.Join("_", key, suffix);
        if (!TimeRecordDic.ContainsKey(key)) TimeRecordDic.Add(key, new TimeRecordItem(key, DateTime.Now));
        else if (TimeRecordDic[key].IsEnd) TimeRecordDic[key].AddTimeSets(DateTime.Now);
        else TimeRecordDic[key].TimeSets.Last().SetEndTime(DateTime.Now);
    }
    public void OutputDebugWriteLine()
    {
        foreach(var content in GetOutputContents())
        {
            System.Diagnostics.Debug.WriteLine(content);
        }
    }
    public void OutputConsoleWriteLine()
    {
        foreach(var content in GetOutputContents())
        {
            System.Console.WriteLine(content);
        }
    }
    //Private Method
    private IEnumerable<string> GetOutputContents()
    {
        var TimeSets = new List<TimeSet>();
        foreach (var item in TimeRecordDic.Values)
        {
            TimeSets.AddRange(item.TimeSets);
        }
        foreach (var r in TimeSets.OrderBy(rr => rr.StartTime))
        {
            yield return string.Join(",", ClassName, r.Key, r.StartTime.ToString(), r.EndTime.ToString(), r.ExecutionTime.ToString());
        }
    }
    //Constructor
    public TimeMeasure()
    {
        TimeRecordDic = new Dictionary<string, TimeRecordItem>();
        ClassName = new System.Diagnostics.StackFrame(1).GetMethod().ReflectedType.FullName;
    }
    //Private Class
    private class TimeRecordItem
    {
        //Property
        public string Key { get; private set; }
        public List<TimeSet> TimeSets { get; private set; }
        public bool IsEnd {  get { return TimeSets.Last().EndTime != null; } }
        //Public Method
        public void AddTimeSets(DateTime time)
        {
            TimeSets.Add(new TimeSet(Key, time));
        }
        //Constructor
        public TimeRecordItem(string key, DateTime time)
        {
            Key = key;
            TimeSets = new List<TimeSet> { new TimeSet(Key, time) };
        }
    }
    private class TimeSet
    {
        //Property
        public string Key { get; private set; }
        public DateTime StartTime { get; private set; }
        public DateTime? EndTime { get; private set; }
        public decimal? ExecutionTime
        {
            get
            {
                if (EndTime == null) return null;
                var diff = EndTime.Value - StartTime;
                return (decimal)diff.TotalMilliseconds / 1000;
            }
        }
        //Public Method
        public void SetEndTime(DateTime time)
        {
            EndTime = time;
        }
        //Constructor
        public TimeSet(string key, DateTime time)
        {
            Key = key;
            StartTime = time;
        }
    }
}

動作

以下のようなサンプルクラスで動作確認

public class Sample
{
    private TimeMeasure _timeMeasure = new TimeMeasure();

    public void Execute()
    {
        _timeMeasure.Record();
        TestMethod1();
        TestMethod2();
        TestMethod1();
        _timeMeasure.Record();
        _timeMeasure.OutputConsoleWriteLine();
    }
    private void TestMethod1()
    {
        _timeMeasure.Record();
        System.Threading.Thread.Sleep(1000);
        _timeMeasure.Record();
    }
    private void TestMethod2()
    {
        _timeMeasure.Record();
        _timeMeasure.Record(suffix: "処理1");
        System.Threading.Thread.Sleep(1000);
        _timeMeasure.Record(suffix: "処理1");
        System.Threading.Thread.Sleep(1000);
        _timeMeasure.Record();
    }
}

実行結果

ConsoleAppForDebug.Program+Sample,Execute,2021/01/17 1:14:04,2021/01/17 1:14:08,4.0148715
ConsoleAppForDebug.Program+Sample,TestMethod1,2021/01/17 1:14:04,2021/01/17 1:14:05,1.0005907
ConsoleAppForDebug.Program+Sample,TestMethod2,2021/01/17 1:14:05,2021/01/17 1:14:07,2.0018408
ConsoleAppForDebug.Program+Sample,TestMethod2_処理1,2021/01/17 1:14:05,2021/01/17 1:14:06,1.0007147
ConsoleAppForDebug.Program+Sample,TestMethod1,2021/01/17 1:14:07,2021/01/17 1:14:08,1.000481

どのクラスのどのメソッドで実行にどれくらいかかったかがちゃんと計測できてそう

説明

いくつかピックアップして説明します

簡単に仕込みたい!

調査なので時間をかけずに簡単に仕込めるようにしたかったです。
同じコードの貼り付けのみで仕込んでいけることを目指しました。

public TimeMeasure()
{
    TimeRecordDic = new Dictionary<string, TimeRecordItem>();
    ClassName = new System.Diagnostics.StackFrame(1).GetMethod().ReflectedType.FullName;
}

コンストラクタでStackFrameを用いて呼び出し元のクラスを取得します。

public void Record(string key = null, string suffix = "")
{
    if (key == null) key = new System.Diagnostics.StackFrame(1).GetMethod().Name;
    if (!string.IsNullOrEmpty(suffix)) key = string.Join("_", key, suffix);
    if (!TimeRecordDic.ContainsKey(key)) TimeRecordDic.Add(key, new TimeRecordItem(key, DateTime.Now));
    else if (TimeRecordDic[key].IsEnd) TimeRecordDic[key].AddTimeSets(DateTime.Now);
    else TimeRecordDic[key].TimeSets.Last().SetEndTime(DateTime.Now);
}

測定の開始・終了用のメソッドでもStackFrameを用いて呼び出し元のメソッド名を取得するようにしてます。
加えて、開始か終了の判断をTimeSetクラスで行うようにすることでRecord()を呼び出すだけでいいようにしてます。
結果サンプルコードのように_timeMeasure.Record();を計測したい部分に張り付けていくだけで仕込むことができます。

メソッド内の特定の処理を計測したい!

メソッド内の特定の部分の処理時間を計測したい場合もあるので、
Recordメソッドではsuffix引数を用意してます。
suffixが渡された場合は、呼び出し元メソッド名と渡された文字列を"_"で結合してkeyとして使用します。
※サンプルコードのTestMethod2の部分

private void TestMethod2()
{
    _timeMeasure.Record();
    _timeMeasure.Record(suffix: "処理1");
    System.Threading.Thread.Sleep(1000);
    _timeMeasure.Record(suffix: "処理1");
    System.Threading.Thread.Sleep(1000);
    _timeMeasure.Record();
}
ConsoleAppForDebug.Program+Sample,TestMethod2,2021/01/17 1:14:05,2021/01/17 1:14:07,2.0018408
ConsoleAppForDebug.Program+Sample,TestMethod2_処理1,2021/01/17 1:14:05,2021/01/17 1:14:06,1.0007147
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む