FROM ME TO YOU

oh my bizarre life !!

イテレータ

クラス内において反復処理の機能を実装するためのforeachステートメントは、とかくプログラムコードが複雑に、かつ冗長になってしまうことがあります。 このような場合はイテレーターを利用することで反復処理のコードをシンプルにすることができます

参考書の説明を読んでも???だったけど、実際にコード書いてみたらなんとなくわかったような気がする。

下のコードの例のように、反復中に条件を挟みたい場合なんかはメインプログラム側で制御が必要になってくるけど、イテレータを使えば反復処理を外に出すことができるからメインプログラムをシンプルにできるってことかな。 うまく言語化できてないけど、こんな感じかな。

    class Program
    {
        public static IEnumerable MethodShow(int days)
        {
            DateTime dt = DateTime.Today;
            for (int i = 1; i <= days; )
            {
                if (dt.DayOfWeek != DayOfWeek.Monday && dt.DayOfWeek != DayOfWeek.Thursday)
                {
                    yield return dt;
                    i++;
                }
                dt = dt.AddDays(1);
            }
        }


        static void Main(string[] args)
        {
            foreach(DateTime dt in MethodShow(5))
            {
                Console.WriteLine(dt.ToString("yyyy年MM月dd日(ddd)"));
            }
        }
    }
続きを読む

型パラメータを持つクラスを実装してみる

ジェネリッククラスやディクショナリークラスの型パラメータは独自に実装したクラスにも適用できる。

今回の例だと普通にジェネリック使えばよさそうだけど、インデクサ(setやget)が実装できるので、この辺りに処理が挟めむケースとかなら便利かもしれない。

    class Program
    {
        public class ListTest<T>
        {
            T[] list = new T[100];
            int add;

            public void AddItem(T item)
            {
                list[add++] = item;
            }

            public T this[int Index]
            {
                get
                {
                    return list[Index];
                }
                set
                {
                    list[Index] = value;
                }
            }
        }

        static void Main(string[] args)
        {
            // string型の配列を作成
            ListTest<string> list = new ListTest<string>();

            list.AddItem("hogehoge");
            list.AddItem("fugafuga");

            Console.WriteLine(list[0]);
            Console.WriteLine(list[1]);

            // DataTime型の配列を作成
            ListTest<DateTime> list2 = new ListTest<DateTime>();
            list2.AddItem(DateTime.Today);

            Console.WriteLine(list2[0]);

            // 普通にジェネリッククラスで作ってみる
            List<DateTime> list3 = new List<DateTime>();
            list3.Add(DateTime.Today);

            Console.WriteLine(list3[0]);
        }
    }
続きを読む

C# の配列の基本を復習。配列、リストアレイ、ジェネリック、ディクショナリ

コレクションについて復習をかねて色々調べてみた

まずは普通の配列

        static void Main(string[] args)
        {
            int[] ArryTest = new int[5];

            for(int i = 0;i < 5; i++)
            {
                ArryTest[i] = i + 100;
            }

            for (int i = 0; i < 5; i++)
            {
                Console.WriteLine(ArryTest[i]);
            }

        }

出力

100
101
102
103
104
続きを読む

FileSystemWatcherを使って特定フォルダの監視(シングルスレッド)

これまた仕事でよく使う「特定フォルダを監視してファイルが生成されたら何らかのアクションを行う」という機能を実装してみた。

まぁ「何らかのアクション」って書きましたけど、「テキストファイルをDBに取り込む」のが大半なんですけどねw

とりあえずファイルの生成アクションは下記で取得可能らしい。

FileSystemWatcher.NotifyFilter = NotifyFilters.FileName

本来はWindowsFormアプリケーションで実装すべきなんだけど、マルチスレッドプログラミングの知識が必要らしいので今回はここまで。

FileSystemWatcher クラス (System.IO)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;    // 追加

namespace FileSystemWatcherTest
{
    class Program
    {
        static void Main(string[] args)
        {
            FileSystemWatcher watcher = new FileSystemWatcher();
            watcher.Path = @"C:\tmp";
            watcher.Filter = "*.csv";
            watcher.IncludeSubdirectories = false;
            
            //watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
            //                        | NotifyFilters.FileName | NotifyFilters.DirectoryName;

            watcher.NotifyFilter = NotifyFilters.FileName;  // ファイルの生成ならこれだけでよい

            watcher.Changed += new FileSystemEventHandler(OnChanged);
            watcher.Created += new FileSystemEventHandler(OnCreated);
            watcher.Deleted += new FileSystemEventHandler(OnDeleted);
            watcher.Renamed += new RenamedEventHandler(OnRenamed);

            watcher.EnableRaisingEvents = true;
            Console.WriteLine(watcher.Path + "を監視中...");
            Console.ReadKey();

        }

        private static void OnRenamed(object sender, RenamedEventArgs e)
        {
            Console.WriteLine("Rename: " + e.FullPath + " " + e.ChangeType);
        }


        private static void OnDeleted(object sender, FileSystemEventArgs e)
        {
            Console.WriteLine("Delete: " + e.FullPath + " " + e.ChangeType);
        }

        private static void OnCreated(object sender, FileSystemEventArgs e)
        {
            Console.WriteLine("Create: " + e.FullPath + " " + e.ChangeType);
        }

        private static void OnChanged(object sender, FileSystemEventArgs e)
        {
            Console.WriteLine("Change: " + e.FullPath + " " + e.ChangeType);
        }

    }
}

TextFieldParserのサンプルを作ってみた

仕事でCSVやらTXTやらのテキストファイルを扱うことが多いのでTextFieldParserメソッドのサンプルを作ってみた。

固定長の場合、FieldWidthsプロパティの文字幅はバイト単位ではなく文字数単位らしい。 使えない…

[参照の追加] で Microsoft.VisualBasic.dll の追加を忘れずに。

データ

"11111","AAAA""AA"
"22222","BBBBBB "
#"22222","BBBBBB "

ソース

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using Microsoft.VisualBasic.FileIO;

namespace TextFieldParserTest
{
    class Program
    {
        static void Main(string[] args)
        {
            
            List<Data> CsvData = new List<Data>();
            string csvFileName = @"C:\tmp\test.csv";    // ファイル名

            Encoding Encode = Encoding.GetEncoding("Shift_JIS");    // Encode指定
            using (TextFieldParser Parser = new TextFieldParser(csvFileName, Encode))
            {
                Parser.TextFieldType = FieldType.Delimited;    // フィールド区切りタイプ
                Parser.Delimiters = new string[] { "," };      // 区切り文字
                Parser.HasFieldsEnclosedInQuotes = true;       // ダブルコーテーション区切り
                Parser.CommentTokens = new[] {"#"};            // レコード先頭のコメント文字
                Parser.TrimWhiteSpace = true;                  // フィールドの前後スペースを削除

                // データ読み込み
                while (!Parser.EndOfData)
                {
                    string[] fields = Parser.ReadFields();
                    Data data = new Data();
                    data.F1 = fields[0];
                    data.F2 = fields[1];
                    CsvData.Add(data);
                }

                // Console出力
                foreach (var n in CsvData)
                {
                    Console.WriteLine(n.F1+" "+n.F2);
                }
                Console.ReadKey();
            }

        }

        public class Data
        {
            public string F1 { get; set; }
            public string F2 { get; set; }
        }

    }
}