20200706のC#に関する記事は11件です。

[C#/WPF] プライマリディスプレイ(1番の画面)の全体の大きさ/作業領域の大きさを取得する

もくじ
https://qiita.com/tera1707/items/4fda73d86eded283ec4f

やりたいこと

アプリの起動時、モニターの大きさに合わせて、ウインドウのサイズを調節したい。
そのために、今のモニターの大きさを取得したい。

やり方

SystemParametersクラスの、WorkArea.Width/WorkArea.HeightもしくはPrimaryScreenWidth/PrimaryScreenHeightを使う。

使うもの 中身
SystemParameters.WorkArea.Width
SystemParameters.WorkArea.Height
プライマリモニタの作業領域の幅と高さ
SystemParameters.PrimaryScreenWidth
SystemParameters.PrimaryScreenHeight
プライマリモニタ全体の幅と高さ

実験①

どんな値が取れるか見てみる。

モニタの並び
image.png

1番モニタ(プライマリモニタ)の設定
image.png

2番モニタの設定(解像度は1番と同じで、125%になっている)
image.png

コード

private void Button_Click(object sender, RoutedEventArgs e)
{
    var w = SystemParameters.WorkArea.Width;
    var h = SystemParameters.WorkArea.Height;
    var pw = SystemParameters.PrimaryScreenWidth;
    var ph = SystemParameters.PrimaryScreenHeight;
    AddLog("WorkArea      幅:" + w + "高さ:" + h);
    AddLog("PrimaryScreen 幅:" + pw + "高さ:" + ph);
}

〇結果
image.png
→1番ディスプレイは、100%設定なので、モニタの素の解像度の値そのまま。

〇プライマリディスプレイを右側のディスプレイにして実行した結果
image.png
→2番ディスプレイは、125%設定なので、それぞれ、1920/1.25、1080/1.25の値になった。
また、アプリはプライマリに設定したディスプレイの方に表示された。

実験②

実験①はタスクバーを「自動的に隠れる」ようにして実施していたので、隠れないようにしてつねに表示されるようにしてから実施してみる。(1番ディスプレイ、100%で実施)

〇結果
タスクバーの分だけ、WorkAreaのほうの縦の値が小さくなった。
PrimaryScreenWidthとHeightは変わらず。
image.png

※タスクバーを上に広げてやったりすると、その分WorkAreaの値は縮む様子。
下の値は、タスクバーを画面の下半分まで広げたときの数字。
image.png

実験③

自分のアプリのウインドウの大きさを、スクリーンのサイズに合わせて調整してみる。
(試しに、プライマリモニタの真ん中に、モニタの作業領域の大きさの3/4の大きさのウインドウを出してみる)

private void Button_Click_1(object sender, RoutedEventArgs e)
{
    var screen_width = SystemParameters.WorkArea.Width;
    var screen_height = SystemParameters.WorkArea.Height;

    this.Width = screen_width * (3.0 / 4.0);
    this.Height = screen_height * (3.0 / 4.0);

    this.Top = screen_height * ((1.0 / 4.0) / 2.0);
    this.Left = screen_width * ((1.0 / 4.0) / 2.0);
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

C#のみを使って、今画像合成アプリを作るとしたら

はじめに

こんにちは!ゲームを教わりたい人とゲームが上手い人をマッチングするサービス
ゲムトレProでGAMER CARDというSNSなどで名刺がわりになる画像を作る機能をリリースしました。
C# で画像を合成する際にどうやってやるかかなり迷ったため記事化しました
trainer_profile (17).png

事前準備

nugetで下記3つをインストールする
この記事では.NET Core 3.1で使用しているが、.NET Frameworkでも使える

  • SixLavors.ImageSharp
  • SixLavors.ImageSharp.Drawing
  • SixLavors.Font

フォントを使用する

var currentDir = Directory.GetCurrentDirectory();
var collection = new FontCollection(); 
var regular = collection.Install($@"{currentDir}/fonts/regular.ttf");
var bold = collection.Install($@"{currentDir}/fonts/bold.ttf");

ローカルから画像をロードする

var image = Image.Load($@"{currentDir}/image.png");

Webから画像をロードする

var httpClient = new HttpClient();
var bytes = await httpClient.GetByteArrayAsync("https://exapmle.com/image.png");
var webImage = Image.Load(bytes);

画像上に画像を書き込む

var image = Image.Load($@"{currentDir}/image.png");
var httpClient = new HttpClient();
var bytes = await httpClient.GetByteArrayAsync("https://exapmle.com/image.png");
var webImage = Image.Load(bytes);
image.Mutate(ctx =>
{
    // 画像をリサイズ
    webImage.Mutate(w => w.Resize(180, 180));
    // 座標を指定して書き込む
    ctx.DrawImage(webImage, new Point(240, 154), 1);
});

画像上にテキストを書き込む

var currentDir = Directory.GetCurrentDirectory();
var collection = new FontCollection(); 
var regular = collection.Install($@"{currentDir}/fonts/regular.ttf");
var image = Image.Load($@"{currentDir}/image.png");

// 32px
var font = regular.CreateFont(32);
image.Mutate(ctx =>
{
   // テキストを書き込む処理
   ctx.DrawText("MKTaro", font, Color.FromRgb(255, 255, 255), new PointF(240, 90));
});

画像上に五角形を書き込む

var currentDir = Directory.GetCurrentDirectory();
var image = Image.Load($@"{currentDir}/image.png");
var backGroundColor = Color.FromRgba(0, 119, 238, 100);
image.Mutate(ctx =>
{
      var point1 = new PointF(742, 344);
      var point2 = new PointF(763, 359);
      var point3 = new PointF(755, 383);
      var point4 = new PointF(729, 383);
      var point5 = new PointF(637, 339);
      // 要素を増やせば、増やした分の多角形となる
      PointF[] curvePoints =
      {
           point1,
           point2,
           point3,
           point4,
           point5
       };
       ctx.FillPolygon(backGroundColor, curvePoints);
});

終わりに

もし、GAMER CARDを作りたい方がいればゲムトレPro登録してみてくださいね

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

C# 例外の詳細な文字列表現を返却する方法

このまま動作します。
コピぺ、編集して利用するためのコードの断片です。
自由に使って頂いて構いません。

例外を以下のような文字列表現にして返却します。
内部例外の入れ子をサポートしています。

返却文字列
System.Exception
例外Bをキャッチして例外Cが送出されました
   場所 テスト.Form_Test.Button1_Click(Object sender, EventArgs e) 場所 C:\***\Form_Test.vb:行 17

InnerException:
System.Exception
例外Aをキャッチして例外Bが送出されました
   場所 テスト.Form_Test.Button1_Click(Object sender, EventArgs e) 場所 C:\***\Form_Test.vb:行 13

InnerException:
System.Exception
例外Aが送出されました
   場所 テスト.Form_Test.Button1_Click(Object sender, EventArgs e) 場所 C:\***\Form_Test.vb:行 10
呼び出し方法.cs
using System;

try
{
    // ...何らかの処理...
}
catch (Exception ex)
{
    Console.WriteLine(ToDetailedString(ex));
}

以下の共通処理を任意の場所に貼り付ければそのまま使用できます。

共通処理.cs
using System;
using System.Text;

/// <summary>
/// 例外の詳細な文字列表現を返却する。
/// 
/// キャッチした例外をToDetailedString(ex)として呼び出すと、その例外の型、メッセージ、スタックトレース、入れ子になっている全ての内部例外の左記の文字列表現を返却する。
/// キャッチした例外からデバッグ用の文字列を取得したい状況を想定している。
/// 
/// たとえは、3階層の入れ子の例外を渡すと以下のような文字列を返却する。
/// 
/// ------------------------------------------------------------------------------------------------------
/// System.Exception
/// 例外Bをキャッチして例外Cが送出されました
///    場所 テスト.Form_Test.Button1_Click(Object sender, EventArgs e) 場所 C:\***\Form_Test.vb:行 17
/// 
/// InnerException:
/// System.Exception
/// 例外Aをキャッチして例外Bが送出されました
///    場所 テスト.Form_Test.Button1_Click(Object sender, EventArgs e) 場所 C:\***\Form_Test.vb:行 13
/// 
/// InnerException:
/// System.Exception
/// 例外Aが送出されました
///    場所 テスト.Form_Test.Button1_Click(Object sender, EventArgs e) 場所 C:\***\Form_Test.vb:行 10
/// ------------------------------------------------------------------------------------------------------
/// </summary>
/// <param name="ex">文字列表現を取得する対象の例外</param>
/// <returns>例外の文字列表現</returns>
public string ToDetailedString(Exception ex)
{
    var buf = new StringBuilder();

    var currentException = ex;
    while (true)
    {
        buf.AppendLine(currentException.GetType().FullName);
        buf.AppendLine(currentException.Message);
        buf.AppendLine(currentException.StackTrace);

        if (currentException.InnerException == null)
        {
            break;
        }
        else
        {
            currentException = currentException.InnerException;
            buf.AppendLine();
            buf.AppendLine("InnerException:");
        }
    }

    return buf.ToString();
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

C# 例外の詳細な文字列表現を返却する方法 サンプルコード

以下、ExceptionクラスのToStringで十分との結論になりました。
ここで説明しているToDetailedStringは不要でした。

このまま動作します。
コピぺ、編集して利用するためのコードの断片です。
自由に使って頂いて構いません。

例外を以下のような文字列表現にして返却します。
内部例外の入れ子をサポートしています。

返却文字列
System.Exception
例外Bをキャッチして例外Cが送出されました
   場所 テスト.Form_Test.Button1_Click(Object sender, EventArgs e) 場所 C:\***\Form_Test.vb:行 17

InnerException:
System.Exception
例外Aをキャッチして例外Bが送出されました
   場所 テスト.Form_Test.Button1_Click(Object sender, EventArgs e) 場所 C:\***\Form_Test.vb:行 13

InnerException:
System.Exception
例外Aが送出されました
   場所 テスト.Form_Test.Button1_Click(Object sender, EventArgs e) 場所 C:\***\Form_Test.vb:行 10
呼び出し方法.cs
using System;

try
{
    // ...何らかの処理...
}
catch (Exception ex)
{
    Console.WriteLine(ToDetailedString(ex));
}

以下の共通処理を任意の場所に貼り付ければそのまま使用できます。

共通処理.cs
using System;
using System.Text;

/// <summary>
/// 例外の詳細な文字列表現を返却する。
/// 
/// キャッチした例外をToDetailedString(ex)として呼び出すと、その例外の型、メッセージ、スタックトレース、入れ子になっている全ての内部例外の左記の文字列表現を返却する。
/// キャッチした例外からデバッグ用の文字列を取得したい状況を想定している。
/// 
/// たとえは、3階層の入れ子の例外を渡すと以下のような文字列を返却する。
/// 
/// ------------------------------------------------------------------------------------------------------
/// System.Exception
/// 例外Bをキャッチして例外Cが送出されました
///    場所 テスト.Form_Test.Button1_Click(Object sender, EventArgs e) 場所 C:\***\Form_Test.vb:行 17
/// 
/// InnerException:
/// System.Exception
/// 例外Aをキャッチして例外Bが送出されました
///    場所 テスト.Form_Test.Button1_Click(Object sender, EventArgs e) 場所 C:\***\Form_Test.vb:行 13
/// 
/// InnerException:
/// System.Exception
/// 例外Aが送出されました
///    場所 テスト.Form_Test.Button1_Click(Object sender, EventArgs e) 場所 C:\***\Form_Test.vb:行 10
/// ------------------------------------------------------------------------------------------------------
/// </summary>
/// <param name="ex">文字列表現を取得する対象の例外</param>
/// <returns>例外の文字列表現</returns>
public string ToDetailedString(Exception ex)
{
    var buf = new StringBuilder();

    var currentException = ex;
    while (true)
    {
        buf.AppendLine(currentException.GetType().FullName);
        buf.AppendLine(currentException.Message);
        buf.AppendLine(currentException.StackTrace);

        if (currentException.InnerException == null)
        {
            break;
        }
        else
        {
            currentException = currentException.InnerException;
            buf.AppendLine();
            buf.AppendLine("InnerException:");
        }
    }

    return buf.ToString();
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

C# 並列処理 コピペ用 サンプルコード チートシート

このまま動作します。
コピぺ、編集して利用するためのコードの断片です。
自由に使って頂いて構いません。

パターン1 - インデックス0から9までの並列処理

using System;
using System.Threading.Tasks;

// インデックス0から9までの並列処理。
Parallel.For(0, 10, i => {
    Console.WriteLine(i.ToString());
});
// 全ての並列処理が完了したら、処理がこの先へ進む。

パターン2 - リストの内容で並列処理

using System;
using System.Threading.Tasks;

// リストの内容で並列処理。
var l = new List<String>{"a", "b", "c"};
Parallel.ForEach(l, s => {
    Console.WriteLine(s);
});
// 全ての並列処理が完了したら、処理がこの先へ進む。

パターン3 - 繰り返しを使わない並列処理

using System;
using System.Threading.Tasks;

// 繰り返しを使わない並列処理。
// ここでは4つの処理を並列化しているが、処理数は自由。
Parallel.Invoke(
    () => {
        Console.WriteLine("a");
    },
    () => {
        Console.WriteLine("b");
    },
    () => {
        Console.WriteLine("c");
    },
    () => {
        Console.WriteLine("d");
    }
);
//全ての並列処理が完了したら、処理がこの先へ進む。

パターン4 - 並列処理を立ち上げる

using System;
using System.Threading.Tasks;

// 並列処理を立ち上げる。
Task.Run(() => {
    Console.WriteLine("a");
});
// 処理の終了を待たずに、処理がこの先へ進む。

パターン5 - 並列処理を立ち上げて、処理の終了を待ち合わせる

using System;
using System.Threading.Tasks;

// 並列処理を立ち上げる。
var t = Task.Run(() => {
    Console.WriteLine("a");
});

Console.WriteLine("b");

// 処理の終了を待ち合わせる所でこうする。
t.Wait();

注意事項 - 並列処理内の例外は呼び出し元でキャッチされない

using System;
using System.Threading.Tasks;

Task.Run(() => {
    //並列処理内で送出された例外は呼び出し元でキャッチされない。
    //このように、並列処理内で対処すると良い。
    try
    {
        Console.WriteLine("a");
    }
    catch (Exception e)
    {
        Console.WriteLine(e.ToString());
    }
});
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ASP.NET Core MVC 3.1 雑記 「アクションメソッドをAjax呼び出しに限定する」

はじめに

ASP.NET Core MVC 3.1 雑記となります。
自分が実際に使用したメソッドや手順を、
将来の自分に向けた備忘録として残しています。

今回の流れ

  • Ajax呼び出しを判定するメソッドを作成
  • Ajax呼び出しであるかを検証するアクションセレクターを作成
  • アクションメソッドに適用

今回のゴール

  • 特定のアクションメソッドをAjax呼び出しに限定できる

環境

IDE
Visual Studio 2019
言語
C#

Ajax呼び出しを判定するメソッドを作成

HttpRequest クラスの拡張メソッドとして作成しました。
Headerの「X-Requested-With」が "XMLHttpRequest" であればAjax呼び出しとみなします。
より良い判定方法があれば知りたいです。

    /// <summary>
    /// <see cref="HttpRequest"/> クラスの拡張メソッドを提供するクラスです。
    /// </summary>
    public static class HttpRequestExtensions
    {
        private const string AjaxRequestHeaderItem = "X-Requested-With";
        private const string AjaxRequestHeaderValue = "XMLHttpRequest";

        /// <summary>
        /// Ajaxによるリクエストかどうかを取得します。
        /// </summary>
        /// <param name="self"><see cref="HttpRequest"/></param>
        /// <returns>Ajaxによるリクエストである場合は true それ以外は false</returns>
        public static bool IsAjaxRequest(this HttpRequest self)
        {
            if (self == null)
            {
                throw new ArgumentNullException(nameof(self));
            }
            return self.Headers != null &&
                   self.Headers[AjaxRequestHeaderItem] == AjaxRequestHeaderValue;
        }
    }

Ajax呼び出しであるかを検証するアクションセレクターを作成

上記の IsAjaxRequest メソッドを呼び出して検証します。

    /// <summary>
    /// Ajax呼び出しであるかを検証するアクションセレクターです。
    /// </summary>
    public class AjaxOnlyAttribute : ActionMethodSelectorAttribute
    {
        /// <summary>
        /// <inheritdoc/>
        /// </summary>
        public override bool IsValidForRequest(RouteContext routeContext, ActionDescriptor action)
        {
            return routeContext.HttpContext.Request.IsAjaxRequest();
        }
    }

対象のアクションメソッドに属性として付与

    [HttpPost]
    [AjaxOnly]
    [ActionName("filterIndex")]
    public IActionResult Index(string keyWord)
    {
        //省略
    }

これで、AjaxOnlyAttributeを付与したアクションメソッドはAjax経由でなければ呼び出せないようになりました。

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

ASP.NET Core MVC 3.1 入門 その2 「MVCプロジェクトの基本構造」

はじめに

本記事は将来の自分に向けた備忘録としての意味が強いです。
ASP.NET Core MVC 3.1 プロジェクトの基本構造について、自分が学んだことを記載します。
はじめて ASP.NET Core MVC で開発をする方にとって、「どこに何を書いたらいいかわからない」というのはよくある話だと思いますので、少しでも参考になれば幸いです。

前回の記事

ASP.NET Core MVC 3.1 入門 その1 「Hello World!」

今回のゴール

  • ASP.NET Core MVC 3.1 プロジェクトの基本構造を把握する
  • CoCを理解する

環境

IDE
Visual Studio 2019
言語
C#

ASP.NET Core MVC 3.1 プロジェクトの基本構造

ソリューションエクスプローラーを眺める

前回の記事で作成した「Web アプリケーション(モデル ビュー コントローラー)」テンプレートのソリューションエクスプローラーを眺めてみましょう。

こちらのテンプレートには、最初からMVCプロジェクトに必要な最低限の構成が用意されているので、各フォルダ/ファイルの概要について次項でまとめます。

image.png

各フォルダ/ファイルの概要

今回はルートレベルに限定して記載します。

ファイル/フォルダ 概要
wwwroot スタイルシートやJavascriptライブラリ、画像といった静的なファイルを格納するフォルダ。Webルートと呼ぶ。
Controllers コントローラークラスを格納するフォルダ
Models モデルクラスを格納するフォルダ
Views ビューテンプレートを格納するフォルダ
appsettings.json アプリケーションの稼働に必要な各設定情報を管理するファイル
Program.cs アプリケーションのエントリーポイントを担うクラス
Startup.cs アプリケーションが起動されるタイミングで実行されるメソッドを集めたクラス

Coc(設定より規約)

ASP.NET Core MVCはCoC(Convention over Configuration)という考え方を取り入れて作られています。
和訳すると「設定より規約」となります。

何を言っているかというと、ASP.NET Core MVC では
各フォルダやファイルの名称,配置場所も重要になってきます。

例えば、本来であれば、開発者はコントローラーについて、
例えば以下のような事項を「設定」(決定)しなければなりません。

  • 何をもってコントローラークラスとするか
  • コントローラークラスをどこに配置するか

しかし、ASP.NET Core MVC には以下の「規約」があります。

  • 命名規則
    • コントローラーはクラス名の末尾をControllerとするか、Controller属性を付与しなければならない
  • 継承関係
    • 通常コントローラークラスは「Microsoft.AspNetCore.Mvc.Controller」クラスを継承する
      • 前身のASP.NET MVC では必須
  • 配置場所(名前空間)
    • Controllersフォルダ配下
      • 前身のASP.NET MVC では必須
      • Core MVC では、コントローラーの検出に名前空間は無関係ですが、お作法として

上記の規約に従うことで、開発者は決定しなければならない事項が減り、
アプリケーション固有の開発に力を注ぐことができるというわけです。

この仕組みを生かし、効率的に開発を進めていくためにも、ASP.NET Core MVC では、どこに何を作るべきかを常に考えながら進めていく必要があります。

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

ASP.NET Core MVC 3.1 入門 その1 「Hello World!」

はじめに

本記事は将来の自分に向けた備忘録としての意味が強いです。
ASP.NET Core MVC 3.1 のコントローラーについて、自分が学んだことを記載します。

今回の流れ

  • Controllerとは
  • Controllerを追加する
  • アクションメソッドを実装する
  • Hello World!

今回のゴール

  • ASP.NET Core MVC 3.1 のプロジェクトが作成できる
  • 作成したプロジェクトを実行する

環境

IDE
Visual Studio 2019
言語
C#

ASP.NET Core MVC 3.1 のプロジェクトを作成する

「ASP.NET Core Web アプリケーション」を選択

image.png

任意の「プロジェクト名」及び「ソリューション名」を入力

image.png

テンプレートの選択

今回は「ASP.NET Core 3.1」「Web アプリケーション(モデル ビュー コントローラー)」のプロジェクトを選択します。
MVCテンプレートは、どこに何を書けばいいのか参考になるので、学習資料として優秀です。

場合によっては不要なファイルも含まれていたりするので、著者は「空」のテンプレートを利用することが多いですが、今回は初めてということで、最低限の構成が用意されているこちらのテンプレートを採用しています。
「空」のテンプレートからのセットアップ手順も後続の記事でアップします。

ASP.NET Core Identity のお話はまた別の機会とするので「認証なし」とします。
Dockerも今回は使いません。

  • 認証なし
  • HTTPS用の構成:True
  • Dockerサポートを有効にする:False

image.png

プロジェクトの作成完了

VisualStudioで以下のような画面が立ち上がります。
image.png

作成したプロジェクトを実行する

既にサンプルの画面が用意されているので、そのままF5キーを押下して実行してしまいましょう。

実行

ブラウザにそれっぽい画面が表示されれば成功です!
image.png

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

UnityでVSCodeを使用中、関数ジャンプや参照ができない!の解決方法

この記事について

Unityを使ってる際、スクリプトを書くために用いてたVSCodeがNo definition found forNo reference found forとなってしまっていたので、解決した際の手順を記録。

本記事で使用している環境

  • Microsoft Windows
    Version 1903 (OS Build 18362,900)
    Windows 10

  • Visual Studio Code
    Version: 1.46.1

手順

  1. Unityのプロジェクトで使ってるフォルダ内の、Assembly-CSharpと名がついてる拡張子がcsprojのファイルを削除。
    Assembly-CSharp.csproj
    Assembly-CSharp-Editor.csproj
    Assembly-CSharp-firstpass.csproj

  2. Unityのプロジェクトを開き、Edit > Preferencesを選択。
    External ToolsExternal Script EditorがVisual Studio Codeになっているのを確認。(他のエディターになっている場合は変更する。)

  3. UnityのAssets > Open C# Projectを実行。

  4. Unityのプロジェクトで使ってるフォルダ内で、1.で消したAssembly-CSharpフォルダが新しく生成されているのを確認する。

以上です。
これでVSCodeの関数ジャンプや参照が使えるようになりました。

最後に

今回はこのように解決しましたが、似たような問題の原因と解決方法が同じだとは限らないので、一例として捉えてください。

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

【C#】コムソートとは(コード付き)

コムソートとは

コムソートはバブルソートの改良版です。
安定ソートではないため場合によっては処理が多くなってしまいますが基本的には早いです。

アルゴリズム

  1. 総数 n を 1.3 で割り、小数点以下を切り捨てた数を間隔 h とする。 i=0 とする。
  2. i 番目と i+h 番目を比べ、i+h 番目が小さい場合入れ替える。
  3. i=i+1 とし、i+h>n となるまで3を繰り返す。
  4. hがすでに1になっている場合は入れ替えが発生しなくなるまで上の操作を繰り返す。
  5. h を 1.3 で割り、小数点以下を切り捨てた数を新たに間隔 h とし、操作を繰り返す。

実行結果

コムソート.gif

サンプルコード

    int[] ComdSort(int[] _array)
    {

        // 交換したかのチェックフラグ
        bool isChanged = false;

        // 櫛の間隔を定義します。
        int h = _array.Length;


        // コムソートで配列の中身を昇順で並べ替えます。
        while (isChanged || h > 1)
        {

            // 櫛の間隔を計算します。
            if (h > 1)
            {
                h = Mathf.FloorToInt(h / 1.3f);
            }

            isChanged = false;
            for (int i = 0; i < _array.Length - h; i++)
            {
                // 指定した間隔の要素と比較し、順序が逆であれば入れ替えます。
                if (_array[i] > _array[i + h])
                {
                    // 配列の要素の交換を行います。
                    int temp = _array[i];
                    _array[i] = _array[i + h];
                    _array[i + h] = temp;

                    // 交換フラグをtrueにします。
                    isChanged = true;
                }
            }
        }
        return _array;
    }

まとめ

交換ソートの中では比較的に早いですが安定はしていませんのでたまにソートが遅くなります。
交換ソートの中では比較的に早いです。

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

C#のToStringについて

記事を書いたきっかけ

intやfloat、bool、Vector3の値をシリアライズしてデシリアライズできる処理を実装しようと思って行きついたのが、このToString()。やってることの説明としてはintやfloatの値を文字列として外部に出力して、デシリアライズする際にその値の型で文字列から値に変換している。

実際のコード

下記ではVector3NodeっていうクラスでVector3の値をシリアライズ、デシリアライズしている。

Vector3Node.cs
public class Vector3Node : PropertyNode
{
    private Vector3Field vec3Field;

    public Vector3 Value { get { return vec3Field.value; } set { vec3Field.value = value; } }
    public Vector3Node() : base()
    {
        CreateOutputPort<Vector3>(Port.Capacity.Multi, "Vector3");
        vec3Field = new Vector3Field();
        mainContainer.Add(vec3Field);
    }
    public override string SerializeProperty()
    {
        return Value.ToString();
    }
    public override void DeserializeProperty(string _propertyValue)
    {
        var elements = _propertyValue.Trim('(', ')').Split(',');

        if(elements.Length <= 3)
        {
            var vec = Vector3.zero;
            vec.x = float.Parse(elements[0]);
            vec.y = float.Parse(elements[1]);
            vec.z = float.Parse(elements[2]);
            Value = vec;
        }
    }
}

シリアライズ用の関数でVector3の数値を文字列で返し、デシリアライズの際に渡された文字列を3つに分解してVector3の各メンバに代入して処理させています。
BaseNodeクラスの方でデシリアライズ用の関数を抽象メソッドとして定義して、各クラスでオーバーライドしています。
こうすることで型ごとのクラスで型を意識することなく、文字列でデータの読み書きができるようになります。

後はこのVector3用のParseの処理を拡張メソッドとしてリファクタリングすれば汎用性が出そうですね。

参考サイト

文字列から数値、数値から文字列への変換
https://dobon.net/vb/dotnet/programing/convert.html

Vector3の文字列から値へのの変換の方法
https://teratail.com/questions/109274

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