2015年11月01日

構造体の初期化

C#6.0以前の構造体の初期化

構造体の初期化の基本
クラスと同様にnew演算子で初期化できる。
new演算子による明示的な初期化を行わなくても使える。
    public struct Shop
    {
        public int ID;
        public string Name;
    }

    class Tester
    {
        static void Execute(string[] args)
        {
            // new演算子による初期化
            Shop shop1 = new Shop();
            shop1.ID = 1;
            shop1.Name = "Shop 1";
            // newなしでも大丈夫
            Shop shop2;
            shop2.ID = 11;
            shop2.Name = "Shop 2";
            // こういうのもあり
            Shop shop3 = new Shop
            {
                ID = 3,
                Name = "Shop 3"
            };
        }
    }
構造体のコンストラクタとフィールド初期化子による初期化
引数なしのコンストラクタは定義できない。
フィールド初期化子も定義できない。
(コンパイルが通らない)
    public struct Shop
    {
        public int ID;
        //public int ID = 0;

        public string Name;
        //public string Name = null;
        
        //public Shop()
        //{
        //    ID = 0;
        //    Name = null;
        //}
    }
構造体と自動プロパティの問題
    public struct Shop
    {
        // フィールドではなく自動プロパティとすると
        public int ID { get; set; }
        public string Name { get; set; }
    }
    class Tester
    {
        static void Execute(string[] args)
        {
            Shop shop1 = new Shop();
            shop1.ID = 1;
            shop1.Name = "Shop 1";
            // これがコンパイルエラーとなるようになる
            Shop shop2;
            //shop2.ID = 11;
            //shop2.Name = "Shop 2";
        }
    }

上で定義してある構造体はコンパイラにより以下のように解釈されているから
逆アセンブリすると以下のようになっている。
    public struct Shop
    {
        // 自動プロパティは以下のように展開される

        // バックストアとよばれる実際に値を保持するプライベートフィールド定義
        // 構造体を使う前にはこのバックストアが初期化されている必要がある
        private int _ID;
        private string _Name;

        public int ID
        {
            get { return _ID; }
            set { _ID = value; }
        }

        public string Name
        {
            get { return _Name; }
            set { _Name = value; }
        }
        // 引数なしのコンストラクタがコンパイラにより自動生成され
        // この中でゼロ初期化というフィールドをデフォルト値で初期化
        // する特殊な初期化処理が行われる
        // フィールド初期化子はコンパイラによりコンストラクタに移行
        // されるが構造体はゼロ初期化用に使っているため移動できない
        // ために定義できない
        public Shop()
        {
            _ID = 0;
            _Name = null;
        }
    }
自動プロパティとコンストラクタ
デフォルトコンストラクタを呼べばよい
    public struct Shop
    {
        public int ID { get; set; }
        public string Name { get; set; }

        // 引数なしコンストラクタは定義できない(コンパイラにより自動生成されるため)
        //public Shop()
        //{
        //    ID = 0;
        //    Name = null;
        //}
     
        // バッキングストアの変数名が解らない
        //public Shop(int id,string name)
        //{
        //    ??= id;
        //    ??= name;
        //}

        // プロパティに値を設定するまえにバックストアを初期化する必要がある
        //public Shop(int id,string name)
        //{
        //    ID= id;
        //    Name= name;
        //}

       // デフォルトコンストラクタを明示的に呼べばよい
        public Shop(int id, string name)
            : this()
        {
            ID = id;
            Name = name;
        }
    }

C#6.0から文法が変更されている

C#6.0の言語仕様はMSDNを探してもみつからない。
プレビュー版はここにありますが、リリース版とは若干異なります。
・デフォルトコンストラクタ(引数なしコンストラクタ)が実装可能になるということだったが採用されなかった。(BCLへの影響が大きすぎて断念したとのこと)
・初期化時にプロパティを初期化する場合に直接バッキングストアに値を設定するよう変更された
public struct Shop
    {
        public int ID { get; set; } 
        public string Name { get; set; }

        // コンパイル通らない
        //public Shop()
        //{ }

        // ※これが可能に変更
        public Shop(int id, string name)
        {
            ID = id;
            Name = name;
        }

    }

新たに採用された自動プロパティ初期化は使えない
    // クラスならこういうのが可能になった
    public class Shop
    {
        public int ID { get; set; } = 10;
        public string Name { get; set; } = "def";
    }
    // 構造体では使えない
    public struct Shop
    {
        // public int ID { get; set; } = 10;
        // public string Name { get; set; } = "def";
    }
posted by RR at 02:17 | Comment(0) | 文法 | このブログの読者になる | 更新情報をチェックする

2015年11月10日

祝日の求め方

書き直しました(2017/03/12)。以下のページです。

祝日の求め方 その2



日本では祝日は「国民の祝日に関する法律」という法律で決まっています。

この法律によると、2015年は15日で、2016年は「山の日」が追加されて16日あります。

内閣府にあるこのページに詳しいです。

ただし、これが全てではなくて慶弔事等で特別法が制定されて、例えば1993年のみ6月9日が休日になったりします。

祝日法の改正や特別法の制定は今後どうなるのかはわからんので、アルゴリズムで祝日を算出するのは理論上は無理です。(このような不確定部を除いた算出法はネット上にいくつかサンプルがあります)

業務アプリケーションを構築する場合、このような祝日の他に年末年始休暇や創立記念日などの休みも必要となることからデータベース等に祝日マスタ(または稼働日マスタ)を保持しておくことが一般的なようです。

別解として祝日をウェブサービスから取得するという方法もあります。

GoogleAPIから取得する方法が一般的なようですが、こちらでも同様のサービスがありました。しばらく更新されてないようですがとりあえずちゃんと動くようです。

C#からはこんな風に取得できます。
クエリ文字を変えると他にも取得できます。(詳細は本家ページにあります)

using System.Net;
using System.IO;

        public static bool IsHoliday(DateTime date)
        {
            using (var wc = new WebClient())
            {
                using (var stream = wc.OpenRead("http://s-proj.com/utils/checkHoliday.php?kind=h&date=" + date.ToString("yyyyMMdd")))
                {
                    using (var reader = new StreamReader(stream))
                    {
                        var ret = reader.ReadToEnd();

                        if (ret == "holiday") return true;
                        else if (ret == "else") return false;
                        else throw new ApplicationException();
                    }
                }
            }
        }
posted by RR at 00:48 | Comment(0) | Tips | このブログの読者になる | 更新情報をチェックする

2015年11月21日

「基礎からきちんと知りたい人のC#プログラミング入門」



2015年11月11日に日経ソフトウエアから発売。

開発環境のインストール方法から、基本文法、WindowsFormによるGUI開発、SQLServerを用いたデータベースの扱い方からユニバーサルアプリの開発まで実際にアプリケーションを使いなら学べる。

全くの初学者から文法も覚えて一通りなんでもできる人までお勧め。

ピンポイントで調べものをするのならネットの情報を検索するのが良いんだけれども、網羅的に俯瞰したいのならまだまだ書籍の方が便利だったりします。雑誌サイズでカラー表記もありとても読みやすい。

最近はマイクロソフト謹製の解説本が無いだけに、こういう本は貴重です。積読するよりはさっさと一通り芽を通しておきたい内容でした。

posted by RR at 03:02 | Comment(0) | 書籍 | このブログの読者になる | 更新情報をチェックする

2015年11月30日

C#6.0 実践的プログラミング[入門]講座

C#6.0 実践的プログラミング[入門]講座



出版日は2015年8月25日。お馴染み川俣さんのC#6.0の解説書というか教科書。

VisualStudio2015で始まったC#6.0は公式な資料が乏しいだけに貴重な一冊。

もちろんC#6.0の新機能や新しい文法の紹介の他、既存コードとの整合性の付け方の勘所等の説明も流石です。

これからC#の勉強を始める人が最初に読む本ではないですが、一通りコードを書ける程度の知識ある方でVS2015をお使いの方は一読する価値ありますよ。

posted by RR at 00:19 | Comment(0) | 書籍 | このブログの読者になる | 更新情報をチェックする