The road to C# master trapemiya

C#を中心に、.NETの話題を取り上げます。

ホーム 連絡をする 同期する ( RSS 2.0 ) Login
投稿数  206  : 記事  1  : コメント  523  : トラックバック  21

ニュース

Since 2005年10月26日

わんくま同盟

わんくま同盟

Microsoft MVP


Visual Developer - Visual C#

記事カテゴリ

書庫

日記カテゴリ

2009年7月2日 #

新サイト 『TDD.NET』 をオープンしました
http://bluewatersoft.cocolog-nifty.com/blog/2009/07/tddnet-7562.html

TDD (Test-Driven Development)に関して大変わかりやすく丁寧に書かれています。素敵です。お奨めです。

アジャイル開発しているとあっち直せば知らぬ間にこっちが動かなくなっている経験は誰でもあると思います。コンパイラは文法上のチェックはしてくれますが、仕様レベルのチェックはしてくれません。そこで、テストという形で仕様を満たしているかどうかをチェックするのです。誤解を恐れずに言えば、仕様をチェックするもう一つのコンパイルと言えるのかもしれません。そして、テストというもう一つのコンパイラを作っていると言えるのかもしれません。

biacさんの記事で印象的だったのは、

「 動いているコードを触るな」 という禁句を古いものとし、 リファクタリングを正当化する。 」

「テストコードには詳細な仕様が表現されている。 それは、 ( 嫌な ) 文書作成作業を減らし、 ( 大好きな ) コーディング作業を増やせることになる。」

「TDD は、 アジャイル開発手法から生まれてきた方法なので、 」

でした。特に最後の「TDD は、 アジャイル開発手法から生まれてきた方法なので、 」という文章は、私がいつも言っている「それは何のために存在しているのかを考えてみることが大切である。」の答えになっています。
感謝いたします。

posted @ 10:06 | Feedback (3)

2009年6月15日 #

以下で、ユーザーコントロールのViewModelへどのようにアクセスすれば良いのかということを考えていました。

最近MVVMが面白い
http://blogs.wankuma.com/unyora/archive/2009/06/10/174828.aspx

考え方がある程度まとまったので、整理の意味も込めて以下に書いてみます。

MVVMのパターンを見ていると、ViewとViewModelをXamlだけで結び付けているケースがよくあります。これはこれでWPFの優れた仕組みだと思うのですが、実際にアプリケーションを組む場合、これだと疎すぎて扱いにくい場合が多々あります。
例えば伝票画面に伝票ユーザーコントロールを配置した場合を考えてみます。
伝票画面がPaymentSlipWindow、伝票ユーザーコントロールがPaymentSlipです。
それぞれのViewModelをPaymentSlipWindowViewModel、PaymentSlipViewModelとします。

以下に、PaymentSlipのDataContextに、XamlによってPaymentSlipViewModelをセットしている例を示します。

▼PaymentSlip

<UserControl x:Class="WPFPaymentSlipTest.View.PaymentSlip"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="300" Width="300" Background="AliceBlue"
    xmlns:local="clr-namespace:WPFPaymentSlipTest.ViewModel"    
    xmlns:local2="clr-namespace:WPFPaymentSlipTest.View"
    DataContext="{DynamicResource PaymentSlipViewModelKey}">
        ・
        ・
        ・


▼リソース

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:viewModel="clr-namespace:WPFPaymentSlipTest.ViewModel"                
    xmlns:view="clr-namespace:WPFPaymentSlipTest.View"                
                    >

    <viewModel:PaymentSlipViewModel x:Key="PaymentSlipViewModelKey" />

</ResourceDictionary>


▼PaymentSlipWindow

<UserControl x:Class="WPFPaymentSlipTest.View.PaymentSlipWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WPFPaymentSlipTest.View"
    xmlns:model="clr-namespace:WPFPaymentSlipTest.ViewModel" 
             Height="500" Width="376">

    <Grid ShowGridLines="True">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" MinHeight="300" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <local:PaymentSlip Grid.Row="0" x:Name="PaymentSlip" />
        <Button Grid.Row="1" Height="23" Margin="133,12,0,0" Name="bttn_update"
                   VerticalAlignment="Top" HorizontalAlignment="Left" Width="72"
                   Command="{Binding Path=UpdCommand}">更新</Button>
    
    </Grid>
    
</UserControl>

この状態で、更新ボタンを押してUpdCommandを呼びます。UpdCommandでは、PaymentSlipViewModelが持っているUpdateメソッドを呼んで、伝票データを更新したいのです。
ところが、UpdCommandが定義してあるPaymentSlipWindowViewModelからPaymentSlipViewModelのインスタンスを取得することができませんので、Updateメソッドを呼ぶことができません。なぜなら、PaymentSlipとPaymentSlipViewModelはPaymentSlipWindowのXamlで結びつけられており、PaymentSlipWindowViewModelはそれを一切知ることができないからです。
この場合、PaymentSlipWindowのLoadedイベントでPaymentSlipWindowViewModelに自分のインスタンスを渡すという解決策も考えられます。このようにすれば、PaymentSlipWindowViewModelからPaymentSlipWindowのインスタンスが得られ、そこからPaymentSlipのDataContext経由でPaymentSlipViewModelのインスタンスを得ることができるからです。

しかし、この場合はPaymentSlipのDataContextに、PaymentSlipWindowViewModelからコードでPaymentSlipViewModelをセットしてあげるとスムーズに行きます。このようにしておくと、PaymentSlipWindowViewModelはPaymentSlipViewModeを把握していますので、簡単にPaymentSlipViewModelのUpdateメソッドを呼ぶことができます。

 

▼PaymentSlipWindow

<UserControl x:Class="WPFPaymentSlipTest.View.PaymentSlipWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WPFPaymentSlipTest.View"
    xmlns:model="clr-namespace:WPFPaymentSlipTest.ViewModel"
             Height="500" Width="376">

    <Grid ShowGridLines="True">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" MinHeight="300" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <local:PaymentSlip Grid.Row="0" x:Name="PaymentSlip" DataContext="{Binding Path=PaymentSlips}" />
        <Button Grid.Row="1" Height="23" Margin="133,12,0,0" Name="bttn_update"
                                     VerticalAlignment="Top" HorizontalAlignment="Left" Width="72"
                                     Command="{Binding Path=UpdCommand}">更新</Button>
    
    </Grid>
</UserControl>


▼PaymentSlipWindowViewModel

    class PaymentSlipWindowViewModel : ViewModelBase
    {
        private PaymentSlipViewModel _paymentSlips;

        public PaymentSlipViewModel PaymentSlips
        {
            get
            {
                if (_paymentSlips == null)
                    _paymentSlips = new PaymentSlipViewModel();

                return _paymentSlips;
            }
        }
        ・
        ・
        ・

以上をまとめると、MVVMパターンでViewとViewModelをどう結び付けるかは自由ですが、XAMLだけで結び付けてしまうと疎結合が強すぎて、コードから扱いにくくなるということです。もちろん、DataTemplateによるViewとViewModelの結び付けなど、XAMLだけで結び付けると大変便利な場合もありますが、これがMVVMパターンの十分条件では無いということです。

そのことにようやく気がつきました。

posted @ 17:38 | Feedback (4)

2009年5月19日 #

型付きデータテーブルをバインドした際に、一般的には以下のようなバインド式を書くであろう。

{Binding Path=FirstName} 

ここでは列名をFirstNameとしている。これは以下のように書いてもうまくいく。

{Binding FirstName}
{Binding Path=[FirstName]}
{Binding Path=.[FirstName]} 

また、FirstNameが3番目の列であれば、

{Binding Path=[2]}

とも書くことができる。

つまり、[]内は必要に応じて列名とインデックスを読み替えているのである。
さて、ここで疑問が生じる。もし列名が2であれば、

{Binding Path=[2]}

は、2という列名の値をバインドするのであろうか? それとも3番目の列の値をバインドするのであろうか? ちなみに{Binding Path=["2"]} という書き方はできない。

試してみると、2という列名にバインドしている。 ところで、

{Binding Path=2} 

と書いても2という列名にバインドすることになる。困った。このような場合、3番目の列にバインドするにはどう書けばいいんだろうか?

とりあえずコンバーターで実現することはできた。

{Binding Path=., Converter={StaticResource converter},ConverterParameter=3} 
public class MyConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if ((bool)(DesignerProperties.IsInDesignModeProperty.GetMetadata(typeof(DependencyObject)).DefaultValue))
        {
            return "";
        } 

        return ((System.Data.DataRowView)value).Row[int.Parse(parameter.ToString())];
    } 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
} 

こうするしか無いのであろうか? もっとも列名を数字にしなければ良いだけなんですが(^^;

posted @ 16:18 | Feedback (0)

2009年5月15日 #

結構以下のページが役に立ちます。

Windows フォーム コントロールおよび同等の WPF コントロール
http://msdn.microsoft.com/ja-jp/library/ms750559(VS.80).aspx

例えば、CollectionViewSourceって何?ってMSDNで調べると、「CollectionView クラスの Extensible Application Markup Language (XAML) プロキシ。 」と書いてある。何となくそういうことかぁとは理解できるが、なんかすきっとわかった気がしない。でも以下のページを見るとBindingSourceと同等と書いてある。
すっきりわかりました。(^^

#でもこのページですっきりわかるのはCollectionViewSourceぐらいかなぁ (^^;

posted @ 17:17 | Feedback (0)

2009年4月24日 #

正規表現において、空文字はどうやら特別扱いされています。
例によって調査結果を元に動作を推測していますので、誤りがあればご指摘下さい。m(_ _)m

abc
に対して
.*
とすると何がマッチするだろうか?

答えはabcと空文字です。なぜ空文字がマッチするのだろうか?
実験すると、
^.*
だとabcにしかマッチしない。
.*$
だとabcと空文字にマッチする。ということは空文字が$の直前にあるようだ。

調査・・・調査・・・調査・・・

どうやら正規表現上、abcというのは以下のように考えられるとのことだ。

行頭 空文字 a 空文字 b 空文字 c 空文字 行末

要するに間に全部空文字が入っているわけだ。

.*はできるだけ長い文字列にマッチするから、
空文字 a 空文字 b 空文字 c 空文字
にマッチしている。つまり、abcだ。次に残ったのは行末だ。この検査対象の行末の前にも空文字があると考え、実際には、空文字+行末に対してマッチングを行うことになる。この結果、.*は.の0回繰り返しとなり、空文字がマッチする。マッチを2回にわけて考えれば、

行頭 空文字 a 空文字 b 空文字 c 空文字

でマッチ、

空文字 行末

でマッチとなったわけだ。上記だと

行頭 空文字 a 空文字 b 空文字 c 空文字 空文字 行末

と行末に空文字が2つ続くイメージになるが、空文字は元々存在せず、検査する際には常に存在すると考えるのであろう。それに空文字なのでいくつあっても空文字一つと同じである。というより何個という概念がない。(虚数のような感じか?)

以上のように考えると、^.*が空文字にマッチしなくて、.*$がマッチするのも説明が付く。

では、
abc
に対して
b*
とすると何がマッチするだろうか?

答えは、空文字、b、空文字、空文字である。
動作的にはたぶんこうだ。
行頭の次の空文字はbの0回の繰り返してでマッチ。・・・(1)
次のaはマッチしようがないのでスキップ。
次の「空文字 b 空文字」はbと考えられるのでbの1回の繰り返しでマッチ。・・・(2)
残りは「空文字 c 空文字 行末」。
よってcの前の空文字がマッチ。・・・(3)
cはマッチしないのでスキップ。
残りの「空文字 行末」で空文字がマッチ・・・(4)

以上より、空文字、b、空文字、空文字がマッチすることになる。


#以上のこと合ってる? >みなさん。

posted @ 16:39 | Feedback (7)

2009年4月22日 #

正規表現を使って、ある文字列にいくつかの特定の文字列が含まれているかを調べる
http://blogs.wankuma.com/trapemiya/archive/2009/04/18/171635.aspx

にコメントをいただいて、正規表現の先読みに関して理解が足りていないと痛感しましたので、自分なりに調査してまとめてみました。間違ってるというご指摘があれば是非コメントを下さい。よろしくお願いします。

「謎は全て解けた!」と、金田一少年のように言い切れればいいんですけど・・・ 。でも自分ではほぼ満足いくレベルに達したんで公開してみました。添削してもらいたいということもありますがw

では、解説を始めます。

以下の検査対象の文字列があるとします。

abuser unknown? bbbbb unknown user1aaaaaa No such user here a

この時、「user unknown」、「unknown user」、「No such user here」の3つの文字列全てを含むかどうかを検査する正規表現は以下のように書けます。(ただしベストな書き方ではありません。より良い書き方は後述します。)

(?=.*user unknown)(?=.*unknown user)(?=.*No such user here)

ここで(?=)は先読みと呼ばれるものです。いきなりですが先読みという訳は誤解を招きやすく、訳としては適当ではないと思います。英語ではlookaheadやlook-aheadやlook aheadと書かれます。直訳すれば「先を見ろ」ということになります。つまり先は前後の前という意味の先です。先読みとは前方を読みなさいということです。順序的に先に読むということではありません。
(#日本語訳だとわかりにくい場合があるので、その場合には英語の原文で確認されることをお勧めします。これは一般的に言えることです。)

さて、意味がわかったところで先読みの動作を見てみましょう。先読みは、マッチした部分があるとその直前にポインタを置きます。例えば、abcdefという文字列に対する(?=cd)はcdの部分にマッチし、ポインタはbとcの間に置かれます。従って、bcdeにマッチさせるにはb(?=cd)cdeとなります。このように先読みはマッチした部分をマッチの対象として記憶しません。これをキャプチャしないとも言います。言いかればキャプチャした文字列長が0ということであり、幅0とも言われます。

上記のことは次のように言うこともできます。
abcdefという文字列に対してcdという正規表現があった場合、abcdefのcdの部分にマッチし、次の検査開始のポインタはそのマッチした部分の直後に置かれます。したがって例えばbcdeにマッチさせる正規表現はb(cd)eになります。もちろんbcdeと書いてもかまいません。一方、先読みは幅0ですので、このポインタが移動しないということなのです。したがって前述した通り、先読みでは同じ正規表現を b(?=cd)cdeと書く必要があります。lookaheadですので、その場に留まって前方を見ろということなのですしょう。

ところで、最初に書いたように先読みを連続で書いた場合はどうなるでしょうか? この場合は、全ての先読みについて、それぞれが一致した位置が全て合致している場合にマッチしたということになります。
つまり、
(?=.*user unknown)(?=.*unknown user)(?=.*No such user here)
に関して言えば、3つの先読みがそれぞれ一致した位置の全てが合致している場合にマッチしたということになります。
上のことは論理積ですので、3つの先読みをどのような順序で記述しても良いということになります。

ではここで問題です。
以下の検査対象の文字列があるとします。

abcdefg

(?=.*cd)(?=bc)はマッチするでしょうか?
(?=.*cd)(?=de)はマッチするでしょうか?

答えは(?=.*cd)(?=bc)はマッチしますが、(?=.*cd)(?=de)はマッチしません。
なぜなら(?=.*cd)が一致する位置は先頭からcdの直前までですから、先頭、aとbの間、bとcの間の三ヵ所あります。(?=bc)はaとbの間のみ、(?=de)はcとdの間のみになります。
したがって(?=.*cd)(?=bc)はaとbの間が合致しますからマッチしますが、(?=.*cd)(?=de)は合致する位置がないためマッチしないということになります。
同様に考えると、
(?=.*user unknown)(?=.*unknown user)(?=.*No such user here)
も比較する位置がたくさんあって効率悪そうです。上記の3つの先読みはいずれも.*を含むため、先読みが一致すれば一致する位置に必ず先頭が含まれるということです。そこで先頭の位置だけ比較すれば済むように、マッチ条件に先頭の位置を追加しましょう。先頭の位置は^で表します。位置情報なので^も幅0です。
^
(?=.*user unknown)
(?=.*unknown user)
(?=.*No such user here)
の4つの位置の論理積になりますから、

^(?=.*user unknown)(?=.*unknown user)(?=.*No such user here)

のように書くことができます。4つの論理積なので、ちょっとびっくりされるかもしれませんが、
(?=.*user unknown)^(?=.*unknown user)(?=.*No such user here)

(?=.*user unknown)(?=.*unknown user)(?=.*No such user here)^
でもいいんです。

これで4つの先頭の位置が合致したらマッチしたと条件を絞ることができます。

ちなみに(?=.*user unknown)の合致する位置は複数あり得ますが、その場合でもポインタは先頭に置かれます。したがって、以下のような先読みである
(?=.*user unknown).*
にマッチした場合、マッチする文字列は検索対象文字列全体になります。

さて、次に先読みについてもう少し解説します。論理積なので、そのうちの一つである(?=.*user unknown)の動作について説明すれば十分でしょう。なぜなら他の2つもこれと同様の動作になるだけだからです。
では、以下のように先読みが含まれる場合のキャプチャされる文字列について考えてみます。

^.*(?=.*user unknown)

検索対象は既出と同じく
abuser unknown? bbbbb unknown user1aaaaaa No such user here a
です。

先読みで.*user unknownがマッチするところを調べます。とりあえず一致するところが見つかりました。abuser unknownの部分ですね。次に.*について調べます。.*はマッチする最長に一致しようとします。そうすると、先読みの条件を満たす.*の最長はabになります。(?=.*user unknown)は幅0なので、結局この正規表現でキャプチャされたフレーズはab + 幅0 = abということになります。
先読みはバックトラックしないため、つまり複数マッチする部分を見つけようとしないため、正規表現にマッチした部分は一箇所であり、グループ化もされていないのでキャプチャされた部分も一箇所になりますが、通常の正規表現ですとマッチする部分が複数、それぞれのマッチした部分でのキャプチャも複数ということもあり得ます。

上記を理解されれば、
^(?=.*unknown user)や
(?=.*user unknown)や
^
のキャプチャが空白になることは明らかでしょう。^も(?=.*unknown user)などの位置情報は幅0だからです。
^.(?=.*user unknown)
のキャプチャがaになるのも明白ですね。

では、
^.*(?=.*user unknown).
はどうなるでしょうか?(判りにくいですが文末にピリオドがあります)
ab + 幅0 までは良いでしょう。この時、abuser unknownにマッチしていますが、先読み部分はポインタが動きませんから、ポインタはabの後にあることになります。
したがって、.はuになり、abuがキャプチャされることになります。ちなみにマッチしている部分はabuser unknown? bbbbb unknown userです。

^.*(?=.*unknown XXXuser).
としたら、userの前にXXXが付いているため先読み部分がマッチしませんから、正規表現全体としてもマッチしません。したがって何もキャプチャされません。

^.*(?=.*user unknown).*
はもう簡単ですね。検索対象全てになります。ab以下.*ですから、一致する最長の部分となり、すなわちキャプチャは検索対象全てということになります。ちなみに
^(?=.*user unknown).*や
^(?=.*user unknown).*$も
同様の理由で、キャプチャは検索対象全てになります。

以上のように、マッチするかどうかと何がキャプチャされるかとは別物なのでご注意下さい。すなわち、最初に書いた3つの検索フレーズ全てが含まれるかどうかは以下のように書いてもOKです。 ただし冗長になります。

^.*(?=.*user unknown)(?=.*unknown user)(?=.*No such user here).*$

^(?=.*user unknown)(?=.*unknown user)(?=.*No such user here).*$

問題とすべきは、3つの先読みがそれぞれマッチした位置が3つとも合致するかどうかなのです。そういう意味で後ろにある.*や.*$は何の意味もありません。

上記の動作は、Regexクラスから得られるMatchオブジェクトやCaptureコレクションなどで調査しました。

(参考文献) 順不同

▼正規表現の問題集1(基本編)
http://codezine.jp/article/detail/1573

▼■[ruby]正規表現の先読みについて解説してみる
http://d.hatena.ne.jp/rubikitch/20080622/1214080482

▼標準添付ライブラリ紹介 【第 12 回】 正規表現 (1)
http://jp.rubyist.net/magazine/?0019-BundledLibraries

▼正規表現
http://lukewarm.s101.xrea.com/RegEx.html

▼正規表現(先読み)
http://blatoma.blog10.fc2.com/blog-entry-7.html

▼先読み(lookahead)
http://www4.ocn.ne.jp/~kaerume/k2e/regex_3.html

posted @ 13:39 | Feedback (6)

2009年4月18日 #

文字列Aがあるとします。この文字列Aに、複数の文字列のうちどれかが含まれているかどうかを調べる方法として、MSDNフォーラムに以下のようなスレッドが立ちました。

文字列に特定の文字列が存在しているかを調べる方法
http://social.msdn.microsoft.com/Forums/ja-JP/vbgeneralja/thread/1a28ccd0-feb0-49f0-bc60-62debd99a112/

上記のスレッドは、配列を使った検索による方法を題材として進んでいるので、ここでは他の方法として正規表現を使用した方法をご紹介します。

例えば以下のようにすれば、「user unknown」など指定した5つの文字列のうち、どれかを含んでいれば、regex.IsMatch("調査対象の文字列")はtrueを返します。

Regex regex = new Regex(@"user unknown" +
                                   @"|unknown user" +
                                   @"|Unable to deliver to destination domain" +
                                   @"|no mailbox" +
                                   @"|No such user here"
                                   , RegexOptions.IgnoreCase);

if (regex.IsMatch(str))
{
    //見つかった時の処理
       ・
       ・
}
else
{
    //見つからなかった時の処理
       ・
       ・
}

以上は論理和(or。すなわちどれか一つを含んでいる)の例ですが、論理積(and。すなわち全てを含んでいる)の場合は、以下のようにします。

Regex regex = new Regex("^.*" +
                                   "(?=.*user unknown)" +
                                   "(?=.*unknown user)" +
                                   "(?=.*Unable to deliver to destination domainr)" +
                                   "(?=.*no mailbox)" +
                                   "(?=.*No such user here)" +
                                   ".*$"
                                   , RegexOptions.IgnoreCase);
posted @ 0:23 | Feedback (3)

2009年4月7日 #

データベースを設計する
http://blogs.wankuma.com/rti/archive/2009/04/07/170910.aspx

地方在住だとなかなか勉強会にはいけないので、せめて宿題だけでも考えてみる。
幸い期末をくぐり抜けて、やっと今日は少し時間に余裕があるv(^^)

----------------------
先生マスター
先生Id
氏名

----------------------
教科マスター
教科Id
教科名

----------------------
場所マスター
場所Id
場所名

----------------------
先生教科テーブル
先生教科テーブルId
先生Id(外部キー:先生マスター.先生Id)
教科Id(外部キー:教科マスター.教科Id)
担当教科フラグ(担当教科ならtrue)

----------------------
教科場所テーブル
教科場所テーブルId
教科Id(外部キー:教科マスター.教科Id)
場所Id(外部キー:場所マスター.場所Id)

----------------------
時間割りテーブル
時間割りId
曜日
時限
教科Id(外部キー:教科マスター.教科Id)

#教科を各クラスで行う場合は、場所テーブルに「各クラス」というレコードを作成し、それを利用する。

posted @ 15:07 | Feedback (0)

LINQのTipsの記事をご紹介します。

LINQ Deep Dive: Part I
Tips for Delving in to LINQ
http://www.aspnetpro.com/articles/2009/04/asp200904zh_f/asp200904zh_f.asp

私はLINQ To Objectsしか主に使いませんので、Tips SixとTips Sevenを読みました。Tips SixはLINQの書き方によってパフォーマンスに差が出るということ、Tips SevenはLINQの動作をよく知っていないと見つけにくいバグになるというものでした。Tips SixはSQLの書き方にも似たようなことがあるのでなるほどと思いましたし、Tips Sevenは以前に似たようなことを経験済みなのでそうだよね~と思いました。
いずれにしても良い勉強になりました。Part Ⅱが楽しみです。

posted @ 10:38 | Feedback (3)

2009年4月1日 #

基本クラス ライブラリ (BCL) に関するFAQです。メモっておきます。

.NET Framework Developer Center:よく寄せられる質問 (FAQ)
http://msdn.microsoft.com/ja-jp/netframework/aa569605.aspx

posted @ 9:40 | Feedback (0)