20200121のC#に関する記事は7件です。

C#の基礎知識 No.1

今後必要になってくると思うので、Microsoftが出しているチュートリアルの内容を議事録としてまとめました。

文字列の処理

二つの方法がある。

Foobar.cs
string friend = "Tom";
Console.WriteLine("Hello" + friend);

この方法だとエラーを吐くことなく出力が可能ではあるが、一回一回「+」を入れなければならないので面倒。
そのため、

Foobar.cs
string friend = "Tom";
Console.WriteLine($"Hello {friend}");

でも同じ結果が出力される。
文字列の開始引用符の前に$を入れることにより、文字列内に変数が入れることが可能。

文字列の追加操作

トリミング

無駄な空白がある文字列のトリミングを行うことも可能。

Foobar.cs
// 以下のような変数を定義すると
string food = "     apple     ";
Console.WriteLine($"[{food}]");

// このように出力される
 [     apple     ]

そのため、Trimメソッドを用いる

Foobar.cs
string trimFood = food.Trim();
Console.WriteLine($"[{trimFood}]");

 [apple]

// 先頭のみトリミング
trimFood = food.TrimStart();
Console.WriteLine($"[{trimFood}]");

 [apple     ]

// 末尾のみトリミング
trimFood = food.TrimEnd();
Console.WriteLine($"[{trimFood}]");

 [     apple]

置き換え

文字列を置き換えすることも可能。

Foobar.cs
string fav = "Like Movie";
Console.WriteLine(fav);

 Like Movie

//置き換えを行う時はReplaceメソッドを使用する
fav = fav.Replace("Movie", "Running");
Console.WriteLine(fav);

 Like Running

文字サイズ変更

全てを大文字・小文字に変換することも可能。

Foovar.cs
Console.WriteLine(fav.ToUpper());

 LIKE RUNNING

Console.WriteLine(fav.ToLower());

 like runnning

文字列の検索

文字列内に検索文字列が含まれているかどうかを調べることが可能。
出力はTrueFalseのどちらかによるboolean型
メソッドは3種類あり各々に違いがある。

Containts : 文字列のどこかに検索文字列があればTrueを返し、なければFalseを返す
StartsWith : 文字列の先頭に検索文字列があればTrueを返す
EndsWith : 文字列の末尾に検索文字列があればTrueを返す

Foobar.cs
string intro = "I have no friends, but live strongly";
// Contains
Console.WriteLine(intro.Containts("friends"));
Console.WriteLine(intro.Containts("foods"));

// StartsWith
Console.WriteLine(intro.StartsWith("I"));
Console.WriteLine(intro.StartsWith("friends"));

// EndsWith
Console.WriteLine(intro.EndsWith("stringly"));
Console.WriteLine(intro.EndsWith("friends"));

 True
 False

 True
 False

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

【Unity/C#】コルーチンを自前で動かすためにIEnumeratorについて簡単に調べた

コルーチンを自前で動かしたい

コルーチンはMonoBehaviourを継承していればStartCoroutineで動かすことができます。しかし、MonoBehaviourを継承していなくても使いたい場面は割と多いです、多分。
MonoBehaviourなしでコルーチンを動かす方法は調べるとそれなりに出てきますが、そもそもコルーチンで使われているIEnumeratorとはなんぞ?から始めたい所存です。

IEnumeratorインターフェース?

MSDNを見てみるとシンプルに書かれています。

非ジェネリック コレクションに対する単純な反復処理をサポートします。

IEnumeratorインターフェースは反復処理を実現するためのインターフェースになります。
コルーチンはUnityが反復処理をいい感じに実行してくれてる仕組みというわけですね。

反復処理を作って動かしてみる

とりあえず物は試しということでUnityで適当な反復処理を作ってみます。
わかりやすくデバッグログも出してこんな感じに。

SampleCoroutine.cs
public IEnumerator Coroutine() {
    Debug.Log("Coroutine 1");
    yield return 1;

    Debug.Log("Coroutine 2");
    yield return 2;
}

こいつをこんな感じで動かしてみます

SampleCoroutine.cs
public void Sample() {
    var iEnumerator = Coroutine();
    while (iEnumerator.MoveNext()) {
        Debug.Log($"Coroutine Return {iEnumerator.Current}");
    }
}
Console
Coroutine 1
Coroutine Return 1
Coroutine 2
Coroutine Return 2

おもったよりかんたん!

何をやっているの?

まずは反復処理についてです。何気なく使っているyieldですが、yieldを含むブロックのことをイテレータブロックと言います。
大雑把に説明すると「1回の処理でここまでやってね」というブロックになります。yieldには値を返すreturnと処理を抜けるbreakの2つのキーワードがあります。

次にMoveNextです。これはイテレータを次に進ませます。イテレータが進んだ場合はtrueを返すため、whileを使うとイテレータを全て進めることができます。

Currentは反復処理が返した値を保持しているプロパティです。yield returnで返した値がそのまま入ってくる感じですね。
object型なので色んなものを返せます。

SampleCoroutine.cs
public IEnumerator Coroutine() {
    yield return 1;
    yield return 9.6;
    yield return "ほげえ";
}
Console
Coroutine Return 1
Coroutine Return 9.6
Coroutine Return ほげえ

また、Resetに関してですが、こちらは自前で実装する必要があります(実装してないとNotSupportedExceptionがスローされます)。
単純にIEnumeratorインターフェースで実装した反復処理メソッドをやり直したい場合は対象のメソッドを再び取得して動かします。

SampleCoroutine.cs
public void Sample() {
    var iEnumerator = Coroutine();
    while (iEnumerator.MoveNext()) {
        Debug.Log($"Coroutine Return {iEnumerator.Current}");
    }

    // iEnumerator.Reset();     <- NotSupportedExceptionがスローされる
    iEnumerator = Coroutine();
    while (iEnumerator.MoveNext()) {
        Debug.Log($"Coroutine Return {iEnumerator.Current}");
    }
}

思ったよりシンプル!これならStartCoroutineなしでもなんとかなりそう・・・?

WaitFor関係は更に自前で実装しないとダメ

注意点としてWaitForSecounds等は単純にyield returnしただけではうまくいかないです。
よくあるのがyield return WaitForSecondsでカウントをするコルーチンですが、単純にMoveNextをしただけではできません。
MoveNextは1フレーム毎にイテレータを進めるというイメージが良いと思います。この辺はStartCoroutineがいい感じに処理してくれてる部分です。

反復処理の入れ子をやりたい

反復処理から反復処理を実行するような形にすればできます。実はIEnumeratorインターフェースを調べ始めたきっかけでもあります。

SampleCoroutine.cs
public IEnumerator Coroutine() {
    Debug.Log("Coroutine Start");

    var coroutine2 = Coroutine2();
    while (coroutine2.MoveNext()) {
        yield return coroutine2.Current;
    }
    Debug.Log("Coroutine End");
}

public IEnumerator Coroutine2() {
    Debug.Log("Coroutine2 1");
    yield return 1;

    Debug.Log("Coroutine2 2");
    yield return 2;
}

public void Sample() {
    var iEnumerator = Coroutine();
    while (iEnumerator.MoveNext()) {
        Debug.Log($"Coroutine Return {iEnumerator.Current}");
    }
}
Console
Coroutine Start
Coroutine2 1
Coroutine Return 1
Coroutine2 2
Coroutine Return 2
Coroutine End

おしまい

何気なく使っていたコルーチンとIEnumeratorインターフェースですが、思ったよりシンプルでした。
これでもまだ触りの部分だと思いますが、当初の目的を達成しつつある程度は分かった気がしたのでとりあえずOKとしましょう。

何かあったらコメントください。

参考

++C++; // 未確認飛行 C イテレーター
WisdomSoft 処理の分割(コルーチン)
Qiita:[C#]IEnumeratorとIEnumerableを調べた

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

オイラ用、テキストを日本語ボイスに変換してくれるしょぼいWindowsソフトを作ったよ。

下記はBLOG引用になります
VS2017のC#で、テキストを日本語ボイスに変換してくれるしょぼいWindowsソフト( 滑舌が悪いけどYOUTUBERしたい人用)を作ったよ。自分はかなり滑舌悪いくてどもるので、YOUTUBER向かないのですがユーチューバーしてみたい願望があったので、Gさんの「Cloud Text-to-Speech API」で適当に作ってみた。ちなみにまだYOUTUBERするかは決めてない!

APIですが月に0~100万文字までは無料枠なので、大量に使わない限り無料枠で収まると思います。これを他の人に提供しようとするとアウトだろうけど・・。
自分だけが使用するのには何とかその範囲内かと思います。

尚、ソースコードを提供します可変してお好みで使ってください。大量のテキストをボイス変換した場合、ビジーになるかもしれません。そこら辺の処理は入れてません。またGさんからダウンロードしたJSONファイルを置いている階層に合わしてください。

参考にしたサイトは下記になります。
https://cloud.google.com/text-to-speech/docs/quickstart-client-libraries?hl=ja#client-libraries-install-csharp

フォームのオブジェクトの配置は下記になります。画像を参照ください。
2020-01-21_1900.png

using System;
using System.IO;
using System.Windows.Forms;
using Google.Cloud.TextToSpeech.V1;

namespace テキストを日本語ボイスする
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if(richTextBox1.Text.Replace("\r", "").Replace("\n", "") == "")
            {
                MessageBox.Show("文字を入力してください");
                return;
            }

            Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS", "C:\\xxxxx\\xxxxx\\xxxxx\\xxxxx.json", EnvironmentVariableTarget.Process);

            TextToSpeechClient client = TextToSpeechClient.Create();


            SynthesisInput input = new SynthesisInput
            {
                Text = richTextBox1.Text.Replace("\r", "").Replace("\n", "")
            };

            VoiceSelectionParams voice = new VoiceSelectionParams
            {
                LanguageCode = "ja-JP",
                Name = "ja-JP-Wavenet-A",
                SsmlGender = SsmlVoiceGender.Neutral,
            };


            AudioConfig config = new AudioConfig
            {
                AudioEncoding = AudioEncoding.Mp3,
                SpeakingRate = f1(trackBar1.Value),
                Pitch = f2(trackBar2.Value),


            };

            var response = client.SynthesizeSpeech(new SynthesizeSpeechRequest
            {
                Input = input,
                Voice = voice,
                AudioConfig = config
            });

            DateTime dt = DateTime.Now;
            string dttimename = dt.ToString("yyyy-MM-dd-HH-mm-ss");
            using (Stream output = File.Create("voice-" + dttimename + ".mp3"))
            {
                response.AudioContent.WriteTo(output);
                Console.WriteLine($"Audio content written to file 'voice - " + dttimename + ".mp3'");              
                MessageBox.Show("生成しました=>>voice - " + dttimename + ".mp3");
                System.Diagnostics.Process.Start(Directory.GetCurrentDirectory());
            }
        }

        private void trackBar1_ValueChanged(object sender, EventArgs e)
        {

            label3.Text = string.Format("{0:0.00}", f1(trackBar1.Value));
        }

        private void trackBar2_ValueChanged(object sender, EventArgs e)
        {
            label4.Text = string.Format("{0:0.00}", f2(trackBar2.Value));
        }

        private double f1(int a) {

            return Convert.ToDouble(a) / 100;
        }
        private double f2(int a)
        {

            return Convert.ToDouble(a) - 20;
        }

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

メソッド名を日本語(JP)で作ったら分かりやすいんでは

*日本語でコーディングしてもコンパイルが通るみたいな話じゃないよ

言いたいこと

コーディング始めにメソッドを作るとき

パッと見何をやるかわかりにくい ↓

実装.cs
#region event
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
    IsPaintBox();
}
#endregion
#region method
private void IsPaintBox()
{
    if (csrPos[0] <= BOX_POS_LEFT) return;
    if (csrPos[0] >= BOX_POS_RIGHT) return;
    if (csrPos[1] <= BOX_POS_TOP) return;
    if (csrPos[1] >= BOX_POS_BOTTOM) return;

    PaintBox();
}
private int[] GetMousePosition()
{

}
private void DrawBoxFrame()
{

}
private void PaintBox()
{

}
#endregion

ので 日本語でみたら

日本語.cs
#region イベント
マウスが動いたときのイベント()
{
    四角に色を塗るか判断するメソッド();
}
#endregion
#region メソッド
マウスの位置を補足するメソッド()
{

}
// 画面初期描写時にのみ使用する
四角を描写するメソッド()
{

}
四角に色を塗るか判断するメソッド()
{
    マウスの位置を補足するメソッド();
    if(マウスの位置が四角の中なら)
    {
        四角を塗るさせるメソッド();
    }
}
四角を塗るメソッド()
{

}
#endregion

わかりやすくない? って話

問題提起

最初から英字・ローマ字でコーディングすると、めっちゃ頭がこんがらがる...

→なら日本人に合った言語=日本語でコード組み立ててみたらいいんでは
→分かりやすくなった(手間は増える)

メリット(日本語で組むとどうなる)

・わかりやすい≒見やすい → 不足点・変更点が見つけやすい
 これが大きい

・そのままコメント化できる
 英字で作った後にコード読み直しながら概要コメントを作らなくていい

・メソッド名を考えやすくなる
 マウスが四角の上に来たら四角を塗りつぶすメソッド
 →マウスが四角の上に来たら/四角を塗りつぶすメソッド
 →Mouse_On_Square / Paint_Square
 →Paint_Square_On_Mouse
 みたいな

・メソッド作る目的の軸がブレない
 GetMousePosition より マウス位置取得、の方が
 目的が明確に見える ワイは見える

デメリット

・多人数プロジェクトだと 命名の仕方が人によってバラつきが出そう
 日本語→英字に変える時、コーディングルールに気をつけよう
 既存メソッドがあるならそれに合わせよう(既存プロジェクトなら)

・後で結局メソッド名作んなきゃなのでめんどくさい

具体例

作成するプログラムは
「カーソルを四角の中に移動させると、四角の中に色がつく」
とする

流れとして
①イベントとメソッドを1つずつ作る
②メソッドを細分化する
③メソッドへ遷移する条件分岐を考える
④足りなそうなメソッドを足す
⑤完成
の順で考える

①イベントとメソッドを1つずつ作る.cs
マウスが動いたときのイベント()
{
    四角に色を塗るか判断するメソッド();
}
四角に色を塗るか判断するメソッド()
{

}

すごく大まかにつくる ↑

②メソッドを細分化する.cs
四角に色を塗るか判断するメソッド()
{

}
//↓
マウスの位置を補足するメソッド()
{

}
四角を塗るメソッド()
{

}

大まかなメソッドに、何が必要なのかを解体して考える ↑

③メソッドへ遷移する条件分岐を考える.cs
四角に色を塗るか判断するメソッド()
{
    マウスの位置を補足するメソッド();
    if(マウスの位置が四角の中なら)
    {
        四角を塗るメソッド();
    }
}
マウスの位置を補足するメソッド()
{

}
四角を塗るメソッド()
{

}

どう遷移するかぼんやり書く↑

④足りなそうなメソッドを足す.cs
四角の枠を描写するメソッド()
{

}

上の方で遷移書いてみて、足りないなーと思う機能(動作)が出たら追加する
出なければいい

⑤完成.cs
マウスが動いたときのイベント()
{
    四角に色を塗るか判断するメソッド();
}
四角に色を塗るか判断するメソッド()
{
    マウスの位置を補足するメソッド();
    if(マウスの位置が四角の中なら)
    {
        四角を塗るメソッド();
    }
}
マウスの位置を補足するメソッド()
{

}
四角を塗るメソッド()
{

}
四角の枠を描写するメソッド()
{

}

みたいな

最後に

英語がわかりにくいんだ

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

【Unity】個人用にメソッド拡張してみた(随時更新予定

初めに

プログラミングしていると「なんでこの機能ないんだろ?」とか「この機能が欲しい」ということが度々行ったりするようにいつもなっているのでそろそろ拡張していきたいと思いました。

ダウンロード先

内容説明

基本的にUnityを触っている時に使うことを想定して作っています。
使う場合はusing SKTool.Unityをお忘れなく。

目次(クラス、メソッド名)

ListExtension
   ・RemoveNull()
   ・Allocation(T _add,bool _addFlag=false
GameObjectExtension
   ・GetClosestObjectList(List _list)
   ・GetClosestObjectArray(GameObject[] _array)

機能説明

ListExtension

RemoveNull()

List内にnullがある場合すべて削除するメソッド。
89ysu-wim00.gif

Allocation(T _add,bool _addFlag=false)

List内にnullがある場合そのnullに割り当てる、nullがない場合なにもしない。_addFlagがtrueであれば要素内にnullがない場合Addします。
2dkxn-hbh4r.gif    nymrz-q5q2f.gif

GameObjectExtension

GetClosestObjectList(List _list)

渡されたListの中から自身から一番近いオブジェクトを返します。
(自身が青で一番近いオブジェクトが赤になっていますがこれはわかりやすくするために色を変えているだけなのでこの関数を呼んでも色は変わりません)
fhvct-l7dpb.gif

GetClosestObjectArray(GameObject[] _array)

渡された配列の中から自身から一番近いオブジェクトを返します。
(自身が青で一番近いオブジェクトが赤になっていますがこれはわかりやすくするために色を変えているだけなのでこの関数を呼んでも色は変わりません)
fhvct-l7dpb.gif

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

C# implicit explicit

implicit
暗黙のうちに変換。
宣言してもいい。

explicit
暗黙のうちに変換はできない。
明示的変換はできる。

使い方

public class Hoge
    {
        // intをhogeにしたとき
        public static implicit operator Hoge(int a) => new Hoge();
        // Hogeをintにしたとき
        public static implicit operator int(Hoge h) => 3;
    }

    private void Test()
    {
        Hoge h = new Hoge();
        // キャストする必要がない暗黙のうちに変換される。 しても良い。
        int i = h;
        h = i;
        i = h;
    }
public class Sample
{
    public class Hoge
    {
        // intをhogeにしたとき
        public static explicit operator Hoge(int a) => new Hoge();
        // Hogeをintにしたとき
        public static explicit operator int(Hoge h) => 3;
    }

    private void Test()
    {
        Hoge h = new Hoge();

        // int i = h; コンパイルエラー
        int i = (int)h; // OK

        // h = i コンパイルエラー
        h = (Hoge)i; // OK

        // i = h; コンパイルエラー
        i = (int)h // OK
    }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【C#】Listの使い方まとめ

初期化

[型] 変数名 = new List<型>();

要素を指定して初期化するとき
[型] 変数名 = new List<型>({要素});

位置のindex番号で要素を追加

var list = new List();
list.Insert(index, item);

要素のindex番号で要素を削除

var list = new List();
list.RemoveAt(index, item);

今日のつまづいたこと

4つの数字(1,2,3,4)のから作れる2つの整数の組み合わせを求める。

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