Posts tagged ‘C#’

来週は大阪のMIC主催スキルアップカリキュラムセミナーで登壇します!こちら

IMG_4183

という訳で来週は久々に日本マイクロソフトの大阪支店での登壇です。

Microsoft Innovation Center主催のスキルアップカリキュラムセミナーは1週間、C#の基礎編についてお話します。

その中でもちょっと楽しみにしているのが、9月30日実施予定のセミナーでの「オブジェクト指向」についてお話することになりました!

もちろん、他のトピックについても頑張ってお話ししますし、セミナー自体が連続受講を想定しているのでほかの日にも参加していただきたいところですが、実はコミュニティ勉強会での初登壇は「オブジェクト指向」をテーマにセッションだったので、ちょっと感慨深いですw

まぁ、時間の都合もあるのでOOのことばかりお話することはできませんが、私自身楽しみにしております。

お申込みいただいたみなさん、頑張ってお話しますのでよろしくお願いしますねー♪

ツイートツイート
Facebook にシェア
このエントリーをはてなブックマークに追加
[`evernote` not found]

このエントリーは「C# Advent Calendar 2013」の21日目のエントリーです。

前日はterry_u16さんの「【C#】niconicoAPIを使ったりスクレイピングしたり」でした。

今回は時間がなくなってしまって、ちょこっとした内容ですが…。

さて、本年2回めのC# Advent Calendarですが、以前からずっと気になっていたクラスの1つでTupleクラスがあります。

まず、Tupleクラスについて簡単にご説明するところから始めましょう。

Tupleクラス

Tupleとは組みを表す単語で、語源は確かDoubleとかTrippleなどの組み合わせの数字がおおきくなってくるとquintuple(5組み)、sextuple(6組)と増えていく中、徐々に表現しずらくなることから10tuple、11tupleという表現となった・・・と聞いたことがあります(不確定ですみません(^^;)

.NET Framework においては.NET Framework 4より、名前が不確定な複数のオブジェクトをのひとかたまり(1組み)を表現するのにTupleクラスが追加されました。。

利用方法はGenericのメソッドにより生成する形になります。

Tuple.Create<T1>(T1)
Tuple.Create<T1, T2>(T1, T2)
Tuple.Create<T1, T2, T3>(T1, T2, T3)
Tuple.Create<T1, T2, T3, T4>(T1, T2, T3, T4)
Tuple.Create<T1, T2, T3, T4, T5>(T1, T2, T3, T4, T5)
Tuple.Create<T1, T2, T3, T4, T5, T6>(T1, T2, T3, T4, T5, T6)
Tuple.Create<T1, T2, T3, T4, T5, T6, T7>(T1, T2, T3, T4, T5, T6, T7)
Tuple.Create<T1, T2, T3, T4, T5, T6, T7, T8>(T1, T2, T3, T4, T5, T6, T7, T8)

生成されるオブジェクトは構造体であり、値型です。

12/23追記:生成されるTuple自体はクラスから生成された参照型のオブジェクトでした。失礼しました。

http://msdn.microsoft.com/ja-jp/library/vstudio/dd386941%28v=vs.110%29.aspx

http://msdn.microsoft.com/ja-jp/magazine/dd942829.aspx

(いげ太さん、ご指摘いただいたありがとうございました)

 

これに似たような機能としてKeyValuePair構造体がありました。KeyValuePairがKeyとValueのデータを保持するのに対して、Tupleは最大8つの値を保持することが可能で、各項目の取り出しは以下のような形で行えます。

            var tupleData1 = Tuple.Create<int, int, int>(1, 2, 3);
            Console.WriteLine(tupleData1.Item1);
            Console.WriteLine(tupleData1.Item2);
            Console.WriteLine(tupleData1.Item3);

            //こうでも大丈夫
            var tupleData2 = Tuple.Create(1, 2, 3);
            Console.WriteLine(tupleData2.Item1);
            Console.WriteLine(tupleData2.Item2);
            Console.WriteLine(tupleData2.Item3);

 

実行結果は以下の通りです。

image

このように利用方法はとても簡単です。 そのため、テスト用のデモアプリを作ったりする場合には非常に重宝しています。

また、メソッドから複数の値を返す場合にカスタムクラスを作ったり、outパラメータを使ったりしなくても、Tupleで用が足りそうです。

が! いざ、業務で開発するような場合はコレクションなどと異なって、使いどころがなかなか難しい。 だいたいの要件は匿名クラスで足りるでしょうし、敢えて戻り値で返すならきちんとカスタムクラスを定義したほうがよさそう…。

見ての通り、各項目の取り出しは「Item1, Item2…」といった特に名前に特徴のないプロパティによってマジック変数化してしまって難読化されてしまうのが難点。

ただ、単体テストとかならなんとか利用できるのではないか…と思ってやってみました。

テストの対象はこちら。

namespace ClassLibrary1
{
    public class Class1
    {
        public static int Add(int x, int y)
        {
            return x + y;
        }
    }
}

で、単体テストはというと…。

using System;
using System.Collections.Generic;
using ClassLibrary1;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace UnitTestProject1
{
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestMethod1()
        {
            var testCase = new List<Tuple<int, int, int>>()
            {
                Tuple.Create(1, 1, 2),
                Tuple.Create(2, 1, 3),
                Tuple.Create(1, 2, 3)
            };

            testCase.ForEach(c => Assert.AreEqual(Class1.Add(c.Item1, c.Item2), c.Item3));
        }
    }
}

こんな感じ。

んー、やはり匿名クラスでもよい気がしますが…判断はおまかせします(^^;

というワケで、結論のないエントリですみません。

21日目のエントリーは以上になります。

次はmoririringさんです!よろしくお願いします!

ツイートツイート
Facebook にシェア
このエントリーをはてなブックマークに追加
[`evernote` not found]

更新:2015-02-24に多少見やすくなるよう加筆

このエントリーは「C# Advent Calendar 2013」の15日目のエントリーです。

前日はTAKANO Sho / @masaru_b_clさんの「LINQ vs キーブレイク パフォーマンス勝負」でした。

さて、今年のC# Advent Calendarはバラエティに富んでますねー! あまりゆるふわ系のネタが少なくて少しプレッシャーですが、なんとか書いてみたいと思います。

で、何をネタにしようかとC#の予約語を眺めていたら、C#1.0からあるのにバージョンが上がるごとに進化(変化?)している機能でデリゲート・インラインメソッド・ラムダ式がありました。

以前、なにかの席でも話していたのですが、この機能はかなり構文や機能が変化しているので、なにかのタイミングで一度、この流れを纏めておいたほうがいいかも!と思ったので、ちょっとまとめてみることにします。

それではC#1.0の頃のdelegateの復習から。

デリゲート(C# 1.0)

そもそもデリゲート(delegate-直訳すると委任・委託・委譲という意味)とはその名前の通り、処理の委譲を支援するための仕組みとなります。

委譲とは大辞林によると「権限などを他に任せて譲ること」となっています。
たとえば、複数店舗を展開しているスーパーがあったとします。
本部は全店舗で実施する予定のセールの説明をするため、各店舗の店長相当の人を会議に招集します。
このとき、実際にはセールが滞りなく実施できればいいため、店長である必要はなく、セールをきちんと推進する権限を持った人であればだれでもよい訳です。
つまり、このように委譲する場合にはきちんと「委譲することができる人」「条件の定義」が必要となる訳です。

C#においても同じように考えることができて、デリゲートという仕組みでは、まずは処理を委譲することができる関数(メソッド)の条件を定義する必要があります。

そこで、C#のデリゲートでは、まずメソッドの参照を行うために利用する条件を「メソッドのシグネチャ」、つまりメソッドの引数や戻り値を定義することで設定します。 そして定義されたデリゲートはC#では「型」(厳密には参照型)として機能します。

それでは定義方法です。定義は「delegate」という予約語を用いて「メソッド」「引数」「戻り値」などを指定します。

前述のとおり、デリゲートは型として定義することになるので、定義したデリゲートを用いることで、メソッドを格納するための「変数宣言」を行うことができる訳ですね。

以下のサンプルでは「CalculateMethod」という名前のデリゲートを定義しています。
ここではintの戻り値を持ち、2つのint型の引数を持つデリゲートはこんな感じで定義します。


        // デリゲートを定義
        public delegate int CalculateMethod(int x, int y);

 

次に宣言したdelegateを用いて変数宣言を行って、それを利用するところ確認してみましょう。

デリゲートで変数宣言した変数には定義した「メソッドのシグネチャ」と同じシグネチャを持つ「メソッドそのもの」を代入することが可能です。
そして、代入した変数を用いてメソッドを呼び出すことが可能になります。

以下では先ほど定義した「CalculateMethod」を用いて変数宣言を行い、その変数に代入・呼び出しを行ってみたコードです。

  class Sample
{
// デリゲートに代入するためのメソッド(足し算)
public intAdd(intx,int
y)
{
return
x + y;
}

// デリゲートに代入するためのメソッド(引き算)
public intSub(intx,int
y)
{
return
x – y;
}

}

classProgram
{
// デリゲートを定義
public delegate intCalculateMethod(intx,int
y);

static voidMain(string[] args)
{
varmain =newSample
();

// Delegateに代入
CalculateMethodcalc =newCalculateMethod
(main.Add);
Console
.WriteLine(calc(10, 20));

// Delegateに代入
calc =newCalculateMethod
(main.Sub);
Console
.WriteLine(calc(10, 20));

Console.ReadLine();
}
}

 
ご覧のように、デリゲートは参照型のため、「newキーワード」によってインスタンス化を行い、このコンストラクタに「実体となるメソッド」を指定することで代入することができます。
実行結果は以下の通りです。
image

このような手順によってメソッドの呼出を委譲することができる訳です。

ご覧のとおり、CやC++でいうところの関数のポインタに似ていますよね。

これによって、メソッド自体を変数として扱えるため、デリゲート自体をプロパティにしたり、メソッドの引数や戻り値に設定することもできるため、外部にあるオブジェクトのメソッドの呼出を簡単に行えるようになりました。

●複数メソッドの代入

そして、delegateのもうひとつの特徴はdelegateで宣言された変数には「複数のメソッド」を代入することができます。

複数メソッドの代入を行う場合は、「同じシグネチャを持つメソッド」を連結し、変数に代入します。

この代入された変数を利用すことで「連結されたメソッド」をまとめて呼び出すことができます。
ただし、このときの連結されたメソッドの呼出順序については仕様で保証されていないので注意してください。

もともとC#のdelegateはMulticastDelegateクラスから派生することによって実現されています。

そのクラス名からもわかるように、MulticastDelegateでは指定されたメソッドを「呼出リスト」と呼ばれる形で管理されており、1つ以上指定されたメソッドを順次呼び出す機能をもっています。

 

    class Sample

   {

       // デリゲートに代入するためのメソッド(足し算)

        public voidAdd(intx,inty)

        {

      Console.WriteLine(x + y);

        }

     

    // デリゲートに代入するためのメソッド(引き算)

        public voidSub(intx,inty)

        {

      Console.WriteLine(x – y);

        }

    }

 

  classProgram

   {

       // デリゲートを定義

        public delegate void CalculateMethod(intx,inty);

     

    static void Main(string[] args)

        {

      var main = new Sample();

         

      // Delegateに代入

      CalculateMethod calc = new CalculateMethod(main.Add)  + new CalculateMethod(main.Sub);

         

      // 以下でもよい。

            //CalculateMethod calc = new CalculateMethod(main.Add);

            //calc += new CalculateMethod(main.Sub);

         

      calc(10, 20);

           Console.ReadLine();

        }

    }

 

結果は以下の通りです。

image

 

デリゲート(C# 2.0)

基本的なデリゲートの機能的には1.0と大差ないのですが、デリゲートの代入時にインスタンス生成(new デリゲート名)を省略できるようになりました。

これによって宣言にあった冗長な表現が簡略化されています。

            // C# 1.0
            // CalculateMethod calc = new CalculateMethod(main.Add);
            // calc += new CalculateMethod(main.Sub);
            CalculateMethod calc = main.Add;
            calc += main.Sub;

 

匿名メソッド・匿名関数(C# 2.0)

また、C# 2.0では匿名メソッド(anonymous method)・インラインメソッド(inline method)が追加されていました。
インラインメソッドとはdelegate構文を用いて「メソッド名を持たない処理」を記述する方法が提供されました。

        // Delegate
        public delegate int CalculateMethod(int x, int y);

        static void Main(string[] args)
        {
            // 匿名デリゲート
            CalculateMethod calc = delegate(int x, int y) { return x + y; };

            Console.WriteLine(calc(10, 20));
        }

delegateを用いて非常に簡単は処理を記述することに利用されていましたが、今では後述するラムダ式があるため、利用する機会は減りました。

また、以前は前述のように匿名メソッド(anonymous method)や匿名関数(anonymous function)と記されていましたが、先日発売になったプログラミングC# 第7版ではこれらの機能のことを「インラインメソッド」と呼んでいました。
書籍によると根拠としては「C#の仕様書に【匿名関数はvoid型以外を返すインラインメソッドの別名として定義されています。】と記述がある」と記載されてありました。

つまり、「仕様書にはこう書いてるからこれが正しいんだ!」という主張でしたが、一応、念のためVSと一緒にインストールC#の仕様書を確認してみると、「インラインメソッド」ではなく「匿名関数」とがっつり書いてありました(^^;
やはり、きちんと原典は調べないとダメですね。 ちょっと余談でした(^^;

 

定義済みデリゲート型(共通デリゲート型)(C# 3.0/.NET Framework 3.5)

C# 2.0や.NET Framework 2.0で導入したジェネリック(総称性)の機能を用いて、.NET Framework 3.5では以下の3種類のデリゲートが定義されました。

戻り値のない定義済みデリゲートのAction

  • 戻り値を持つ定義済みデリゲートのFunc
  • 論理型のも戻り値を持つ定義済みデリゲートのPredicate

具体的にどのように定義されているかというと

public delegate void Action()

public delegate void Action<in T>(T arg)

public delegate void Action<in T1, in T2>(T1 arg1, T2 arg2)

public delegate void Action<in T1, in T2, in T3>(T1 arg1, T2 arg2, T3 arg3)

public delegate void Action<in T1, in T2, in T3, in T4>(T1 arg1, T2 arg2, T3 arg3, T4 arg4)

public delegate TResult Func<out TResult>()

public delegate TResult Func<in T, out TResult>(T arg)

public delegate TResult Func<in T1, in T2, out TResult>(T1 arg1, T2 arg2)

public delegate TResult Func<in T1, in T2, in T3, out TResult>(T1 arg1, T2 arg2, T3 arg3)

public delegate TResult Action<in T1, in T2, in T3, in T4, out TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4)

public delegate bool Predicate<T>(T arg)

というような感じで定義されています。

 

実は、.NET Framework 2.0で既にAction<T>(T arg)のみ定義されていましたが、その後3.0で、上記のように引数の数が4つあるジェネリックデリゲートまで定義されました。

最新の.NET Framework 4.5ではActionやFuncに指定される引数の数が最大16まであるデリゲートが定義されています。

そのため2.0までに行っていたように新しく「delegateキーワードを使ったデリゲート宣言」を行わなくてよくなり、多くのケースで定義済みのデリゲートを利用することで事足りるようになりました。

    class Sample
    {
        public int Add(int x, int y)
        {
            return x + y;
        }
        public void Write(int s)
        {
            Console.WriteLine(s);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Sample s = new Sample();
            
            // 戻り値のないメソッドをActionデリゲートで
            Action<int> write = s.Write;

            // 戻り値がある関数はFuncデリゲートで
            Func<int, int, int> calc1 = s.Add;

            // 匿名関数を使って宣言
            Func<int, int, int> calc2 = delegate(int x, int y) { return x - y; };

            write(calc1(10, 20));
            write(calc2(10, 20));
        }
    }

 

ラムダ式(C# 3.0)

ラムダ式は簡単に言ってしまうと「デリゲート型」および「式ツリー(ExpressionTree)」を作成するために使用できる匿名関数です。

主にLINQで用いることができるよう追加された仕様ですが、もちろんそれ以外の用途でも利用できます。

ラムダ式を作成するにはラムダ演算子( => ) を用いて左辺にパラメータ、右辺に式やステートメントブロックを置くことで作成できます。

            // =>の左側がパラメータ、右側が式
            Func<int, int> fuctorial = x => x*x;

            // パラメータが複数ある場合は()の中に指定する
            Func<int, int, int> calc2 = (x, y) => x + y;

            // 複数のステートメントになる場合はステートメントブロックを使って、
            // メソッドと同様return文で戻り値を指定する。
            Func<int, int, int> calc3 = (x, y) =>
            {
                int result = x - y;
                return result;
            };

上記のようにラムダ式には式形式のものとステートメント形式のものがあります。

 

また、匿名関数といっても、前述した匿名関数とは見た目以外にもいくつかの違いがあります。

  • ラムダ式の戻り値はデリゲート以外にも式ツリー(Expressionクラスを用いたツリー)も作成が可能。ただし、ラムダ式内でメソッド呼出などを行うと式ツリーの作成ができない。
  • 匿名関数は、インラインで記述できるがメソッドなので、ステートメントブロックの中から定義されているメソッド内の変数にはアクセスできませんが、ラムダ式では「変数のキャプチャ」という機能により下記のサンプルのように上位スコープの変数のアクセスが行える。

        Action<string> GetWriteAction(strings)

{

string text =string.Format(“[{0}]”);

 

// 上位スコープのtextをキャプチャ

return p =>Console.WriteLine({0}:{1}, p, text);

}


ただし、上記のサンプルのように変数をキャプチャした状態で外部メソッドをデリゲートを引き継ぐと、通常メソッド終了時に変数の解放がされるところ、生存期間が長くなることがありますので注意が必要です。

 

まとめ

上記の流れを見ておわかりのように、C#1.0からはLINQ以降の流れの中で構文の書きやすさが著しくと向上しており、構文が簡潔になることでより直感的に利用することができるようになりました。

あらためてC#1.0の頃のデリゲートと今のスタンダードであるラムダ式を見比べてみると

C#1.0の定義

        // デリゲートを定義
        public delegate int CalculateMethod(int x, int y);

C#1.0での利用

            CalculateMethod calc = new CalculateMethod(main.Add);
            Console.WriteLine(calc(10, 20));

 

現在のC#の定義

ほとんどのケースで必要なし(定義済みデリゲートを利用)

現在のC#での利用

            Func<int, int, int> add = (x, y) => x + y;
            Func<int, int, int> sub = (x, y) =>
            {
                int result = x - y;
                return result;
            };

 

このようにかなり簡潔に記述できるようになりました。

 

基礎的な内容の復習ですみません(^^;

 

本当は上記の流れからデリゲートの共変性と反変性まで説明しちゃおうかと思ったけど、それをはじめるとジェネリックも…と長くなりそうだったので、この辺で。

 

それでは次はksasaoさんです!

ツイートツイート
Facebook にシェア
このエントリーをはてなブックマークに追加
[`evernote` not found]

スピーカーさんの都合悪くなったとのことで、急きょピンチヒッターとして「プログラミング生放送」に登壇させていただくことになりました。こちら

セッションは「Leap Motion ではじめるNUIプログラミング」ということで、せっかく購入したのでLeap Motion関連のお話をさせていただく予定です。

当日は仕事の都合で懇親会まではいることができないのですが、プロ生での初登壇ということで楽しみにしています。

ほかにも面白そうなセッションをする有名スピーカーばかりなので私以外のセッションでも十分楽しめると思いますので、是非会場でお会いしましょう!

追記:すでにキャンセル待ちのようです。 さすが、プロ生ちゃんの人気はハンパないっすねー。

ツイートツイート
Facebook にシェア
このエントリーをはてなブックマークに追加
[`evernote` not found]

VS2013Previewに対応したResharper 8.0 Betaが公開されています。こちら

ResharperはJetBrains製のVisual Studioで強力なコーディングサポートを行ってくれるAddinですね。

ReflectorやFxCopなど他ツールとの連携も行われていてC#erの中ではファンが多いツールで有名ですね。

そのResharperが昨日公開されたばかりのVS2013Previewに早くも対応した模様。 VS2013もPreviewで、ResharperもBetaなので、利用は十分気をないといけなさそうですね。

とはいえ、いつも使っているツールだけに、ちょっと気になったのでメモ。

ツイートツイート
Facebook にシェア
このエントリーをはてなブックマークに追加
[`evernote` not found]

この記事はC# Advent Calendar 2012 : ATNDへの参加エントリーです。

昨日はAILightさんの「dynamic型を利用した時のパフォーマンス調査」、

そしてxin9leさんの「拡張DisplayName属性」でした。

 

街はWindowsストアアプリだのALMだのAzureだのWindows Phone 8だのASP.NET MVC 4だのSignalRだのと大騒ぎですが、なんと言ってもクリスマスイヴといえばコンソールアプリですよね?w

というワケで.NET Framework 4.5になってもいまだライブラリ検証などでは大活躍!

コマンドライン大好きな僕らの味方、コンソールアプリケーションの新機能について紹介したいと思います。

 

コンソールアプリケーションといえば、主役はConsoleクラスですが、.NET Framework 4.5になって新機能が登場しています。

Consoleクラスの新機能

リダイレクトの検出を行うAPIが追加されています。

  • Console.IsInputRedirected
  • Console.IsOutputRedirected
  • Console.IsErrorRedirected

通常のコンソール出力を行う場合は特に必要ないかもしれませんが、たとえば色つきのテキストをコンソールに出力する場合など、リダイレクト時にはあまり必要とならない入出力を行う場合の判定用などに利用できそうです。

そこでせっかくなので確認用のサンプル・コード。

   1:      class Program
   2:      {
   3:          static void Main(string[] args)
   4:          {
   5:              if(Console.IsOutputRedirected == false) Console.ForegroundColor = ConsoleColor.Red;
   6:              Console.WriteLine("Merry Christmas!");
   7:              Console.ReadLine();
   8:          }
   9:      }

 

実行結果は以下のような感じですね。

image

つづけてコマンドライン引数でファイルに対する出力を行うリダイレクトを指定します。

プロジェクトのプロパティを開いて、デバッグタブでコマンドライン引数にリダイレクトの指定を記述します。

image

実行結果は以下のようになりました。

image

もちろん、画面(コンソール)には何も表示されていません。

そして、ソリューションエクスプローラーで「すべてのファイルを表示」ボタンをクリックしてDebugフォルダを確認すると…。

image

ファイルができていますね。 もちろん、中身は…。

image

ちゃんと出力されていますね。

もっともForegroundColorはコンソール出力に対する前景色の指定なので、リダイレクトされた場合のファイルの出力には影響はないのですが、今回は不要な処理を省くという目的で利用しています。

リダイレクトされた場合のみヘッダーを表示する・・・といった具合に特定の用途の判定に利用するには便利そうですね。

 

せっかくなので、Consoleクラスのメンバーも少し。

そして、一緒にConsoleクラスのいくつかの機能もご紹介しましょう。

上記のソースコードにもあるForegroudColorプロパティではConsoleの表示色を設定できます。

MS-DOS時代の色付けはESCシーケンスを駆使したものですが、今は簡単ですねー。

そして、ForegroundができるということはBackgroundもできます。

   1:      class Program
   2:      {
   3:          static void Main(string[] args)
   4:          {
   5:              Console.BackgroundColor = ConsoleColor.Red;
   6:              Console.WriteLine("Merry Christmas!");
   7:              Console.ReadLine();
   8:          }
   9:      }

実行結果は以下の通りです。

image

確かにコードの通り実行されているんですが、あまり派手ではありませんでしたね。

そこで、こんなコードを追加してみました。

   1:          static void Main(string[] args)
   2:          {
   3:              Console.BackgroundColor = ConsoleColor.Red;
   4:              Console.Clear();        //追加
   5:              Console.WriteLine("Merry Christmas!");
   6:              Console.ReadLine();
   7:          }

実行結果は以下の通りです。

image

ちょっと派手すぎましたかね(^^;

というワケでよいクリスマスをお過ごしください!

ツイートツイート
Facebook にシェア
このエントリーをはてなブックマークに追加
[`evernote` not found]