ページ

2004年5月26日水曜日

よかった。Visual SourceSafe 2005 は提供されるんだ

Visual Studio 2005 Team System for Team Development のところなんかに 「Visual Studio Team Foundation ではソースコントロールやトラッキング、レポーティング、カスタムポリシーといった開発プロジェクトでの変更を効率的に管理するものが統合されて提供される」 なんてことが書かれていて、ここから Visual Studio 2005 Team System: Enterprise-Class Source Control and Work Item Tracking にリンクされています。


で、「Visual SourceSafe はどうなるの?」 というのが気になってました。
もちろん、Visual SourceSafe (以下 VSS と略) にこだわっているわけではないので Team Foundation でもいいっちゃいいんです。けど、わざわざ "Enterprise-Class" なんて銘打ってますし、ちらっと見てみたところ 「バックエンドに SQL Server を使う」 「500人くらいまでのプロジェクトをサポート」 なんてことが書かれています。確かに、これはこれですばらしいんだけど、小規模プロジェクトとか趣味プログラミングとか 「VSS みたいにセットアップすればすぐに使える、お気楽なバージョン管理システムはなくなっちゃうの?」 と。それが気になってたんです。
VS 2005 CTP March 2004 とかにも VSS 2004 とかの謎なバージョンが入ってたとは思いますが、VSS が今後どうなるのかというアナウンスは見たことがなかったので 「Team Foundation に取って代わられちゃって、VSS はなくなるっていうことだったら嫌だなぁ」 と。


けど、見つけました(今まで気付いてなかっただけかも知れませんが)。
Microsoft Visual SourceSafe Roadmap
ちゃんと VSS 2005 のことが書いてあります。
しかも、



  • Remote Web Access over HTTP : HTTP か HTTPS で Web Access できる世界中のどこからでも Visual Studio を使って VSS のデータベースに接続できる(VS 2005、IIS、ASP.NET が必要)。

なんて書いてあります(願わくば、VS 2005 を使わなくても VSS のクライアントで HTTP/HTTPS 経由の接続ができるといいんだけど)。
他にも



  • viewer、marge tool、editor などがプラグイン可能になる(サードパーティ製のツールを使うこともできるようになる)。

  • C#、VB.NET といった Managed Code で機能拡張をすることができるようになる。

  • OnBeforeCheckout、OnAfterCheckIn なんかのイベントが使えるようになる。たとえば、チェックインされたら自動ビルドを実行するなど。

  • Unicode、XML をサポート(今さらではあるけど)。

など。
うーん、こいつぁ、かなりうれしい。


もちろん、VSS 2005 は一人きりとか小規模なチーム向けで、それ以外か小規模でもきっちり管理したいときは Team Foundation ということだそうです(まっ、そりゃそうですね)。

2004年5月25日火曜日

C# 2.0 Specification が更新されているそうです

Eric Gunnerson 氏の blog で発見(Eric Gunnerson's C# Compendium


http://msdn.microsoft.com/vcsharp/team/language/default.aspx にある "C# 2.0 Specification" が更新されているそうです。


24. Nullable type
int? という構文です。int? は Nullable<int> の省略表現です。...なんですが、どうやら (値型、参照型、enum型と同じように) Nullable型というのが増えると思ったほうがいいような感じです。
おぉ、24.3.6 に ?? 演算子なんてものを発見。a ?? b としたとき、a は参照型か Nullable型のみが許され、a が null の場合は b が返り、非 null の場合は a が返る、ということのようです。なるほど、これは結構便利かも。


以下は 25. Other Features の覚え書き。


25.1 Property accessor accessibility
プロパティの set、get それぞれ別々に protected とかが付けれるようになる。


25.2 Static classes
new できないクラス。当然、object 以外からは継承できず、すべてのメンバは static でなくてはいけない。


25.3 Namespace alias qualifiers
新しい namespace の指定方法。
  using A = System.IO;
だと A.Stream とやっても自動的に親も捜してしまうので曖昧になってしまうときがある。しかし、A::Stream とすると 「そこだけ」 の参照になる、ということ?


25.4 Extern aliases
これは 25.3 と似てるけど、さらにアセンブリを指定する方法。そのために extern alias なんて構文が増えてる。extern alias しておいて A::Hoge.Page のように指定。


25.5 Pragma directives
#pragma で warning が制御できるようになったって。


25.6 Conditional attribute classes
今までも ConditionalAttribute はあったけど、これを Attribute に適用できるようになるって。Conditional をつけてある Attribute は、その Attribute をつけている class をコンパイルするときに define されていれば Attribute が付加されるし、されていなければ付加されない。

文字列比較のパフォーマンス

どうやら、一部で流行っているようなので...(^^;



String s1 と String s2 があった場合に、両者が同じかどうかを比較するには



  1. s1.Equals(s2)
  2. String.Equals(s1, s2)
  3. s1 == s2

という 3種類の方法があります。
で、「どれが一番速いのよ?」 という話題ですね。


以下は sscli のソースと .NET Framework 1.1 をちょっと覗き見た内容です。


まず、3 の s1 == s2 は単に 2の String.Equals(s1, s2) を呼び出すだけです。
注意:  VB.NET の s1 = s2 は Microsoft.VisualBasic.CompilerServices.StringType.StrCmp を呼び出すそうですが、C# では単に String.operator ==(s1, s2) を呼び出すだけです。ちなみに、operator== は op_Equality とも表記されます(というか、IL 的には op_Equality のほうが正式名だと思いますが)。


次に、2 の String.Equals(s1, s2) ですが、これは
 a. s1 と s2 が同じオブジェクトなら true を返す。
 b. s1 か s2 が null なら false を返す。
 c. どちらでもないときは 1 の s1.Equals(s2) を呼び出す。
となっています。


で、1 は internalcall といって .NET Framework の内部に実装された関数にマップされています。


というわけで、どれが一番速いかは明らかですね。3 は 2 を呼び、2 は 1 を呼ぶ、という実装なんですから、1 が一番速くて 3 が一番遅いということになります。


ただ、ちょっと注意があります。s1、s2 が同じオブジェクトだった場合、もしくは、どちかが null だった場合は 2 が一番速いという結果になることが多いんじゃないかと思います。
ここで、C# だと同じ文字列定数は自動的に同じオブジェクトになります。それは以下のようにすれば確認できます。


string s1 = "aaa";
string s2 = "aaa";
if ((object)s1 == (object)s2) {
    Console.WriteLine("同じオブジェクト");
}

同じ文字列だけど別のオブジェクトを生成したいときは StringBuilder を使ってやればいいようです。


StringBuilder sb1 = new StringBuilder("aaa");
string s1 = sb1.ToString();
StringBuilder sb2 = new StringBuilder("aaa");
string s2 = sb.ToString();
if ((object)s1 == (object)s2)
{
    Console.WriteLine("同じオブジェクト");
}

# 1つの StringBuilder から 2回 ToString() してやっても別々のオブジェクトに
# なるようではありますが。

やっぱり出てた。VS 2005 CTP May 2004

MSDN の Subscriber Downloads に以下のものがすでにあります。


Visual Studio 2005 Community Technology Preview May 2004 - 32 Bit (English)
Visual Studio 2005 Community Technology Preview May 2004 - 64 Bit (English)


# March じゃなくて May だよ。


ちなみに、32 Bit が 2.53GB の ISO イメージ、64 Bit が3.32GB の ISO イメージです。


64 Bit には当然 .NET Framework 2.0 の 64 Bit 版が入っていると想像してるんですが、こんなにサイズが違うのはなんでなんだろう?
求む、人柱(^^;

Visual Studio 2005 Team System なんてものが登場

こちらのページ。
http://msdn.microsoft.com/vstudio/teamsystem/


まだ読んでないんですが(^^
今まで Visual Studio は開発ツール(コードを書いてコンパイルしてデバッグする)ためのものっていう感じでしたが、Visual Studio 2005 からはだいぶイメージが変わるのかな?



  • for Architects

  • for Developers

  • for Project Managers

  • for Team Development

  • for Testers

のそれぞれが紹介されています。


おそらく TechEd で発表されたんでしょうね。詳細情報求む>現地の人(^^;

2004年5月21日金曜日

C# の Generics

今さらながら .NET Framework 2.0 で搭載される Generics のことです。
といっても解説じゃありません(^^;


基本的には以下のような感じですね。
(以下に書いているコードは VS2005 CTP March 2004 では動きました)



private static void TestGenerics()
{
    List<int> l = new List<int>();
    l.Add(0);
    l.Add(1);
    l.Add(2);
    l.Add(3);
 
    // 普通に Count でループ
    for (int i = 0; i < l.Count; ++i)
    {
        Console.WriteLine(l[i].ToString());
    }
 
    // もちろん foreach でもループできる
    foreach (int n in l)
    {
        Console.WriteLine(n.ToString());
    }
}


通常版では自動拡張する配列は ArrayList クラスでしたが、Generics 版は List クラスになってます(たぶん(^^; リファレンスに List が見つからないんですが)。といっても、Generic なだけで使い方は ArrayList とほとんど同じです。


ただ、ArrayList はほんとに単なる 「自動拡張する配列」 でしたが、List にはいろいろとメソッドが増えてます。たとえば、Find とか。で、おもしろいのは、この Find の引数って Inttelisense で 「Predicate match」 って出てくるんですよ。Predicate ってなにかと言うと、
  public sealed delegate bool Predicate(T obj);
という Generic な delegate なんですね。
ついでに言うと、Find の戻り値は Nullable だそうです。なるほど、たとえ T が値型だったとしても、見つからなかったときに null が返せるように Nullable になってるわけですね。


で、Find を使ったコードはというと以下のような感じ。



private static void TestGenerics()
{
    List<int> l = new List<int>();
    l.Add(0);
    l.Add(1);
    l.Add(2);
    l.Add(3);
 
    // 0 か 2 のものを探して表示
    Console.WriteLine(l.Find(IsZeroOrTwo).Value.ToString());
}
 
private static bool IsZeroOrTwo(int n)
{
    return n == 0 || n == 2;
}


ここでは、static なメソッドである IsZeroOrTwo を delegate のコールバックメソッドとして使ってます。この場合 0 と 2 の 2つが見つかりますが、Find は最初に見つかったほうだけを返すので 0 だけが表示されます。
あぁ、そうそう、検索した結果見つからなくて null が返ってきたときのチェックを省略しちゃってますが、もちろん、ほんとはすべきです。


どうでしょ?すごくイイ!と思いませんか?(私は激しく思います。色を変えたくなるくらい)
ただ、C++ の STL を知らないと Predicate の考え方がわかりにくいかもしれませんね。


もう 1つ。List.FindAll もあります。これは見つかったやつをみんな返すっていうメソッドです。なので、戻り値は List です。引数は Find と同じ。
それと ForEach っていうメソッドもあります。これの引数は 「Action action」 です。Action も、
  public sealed delegate void Action(T obj);
です。Predicate との違いは戻り値が void なところだけですね。


この FindAll と ForEach を使うと、



private static void TestGenerics()
{
    List<int> l = new List<int>();
    l.Add(0);
    l.Add(1);
    l.Add(2);
    l.Add(3);
 
    // 0 か 2 のものを探して表示
    l.FindAll(IsZeroOrTwo).ForEach(WriteLine);
}
 
private static bool IsZeroOrTwo(int n)
{
    return n == 0 || n == 2;
}
 
private static void WriteLine(int n)
{
    Console.WriteLine(n.ToString());
}


こんな感じに書けます。


さらに...
delegate は Anonymous Method として書けるはずです。ということは...



private static void TestGenerics()
{
    List<int> l = new List<int>();
    l.Add(0);
    l.Add(1);
    l.Add(2);
    l.Add(3);
 
    l.FindAll(delegate(int n)
    {
        return n == 1 || n == 3;
    }).ForEach(delegate(int n)
    {
        Console.WriteLine(n.ToString());
    });
}


っていう書き方ができるんです。


イイ!イイ!イイ!激しくイイ!
こりゃ楽しいや。

int? - Nullable

一部でうわさになっていた機能ですが、VS2005 CTP March 2004 で実装されていたんですね。全然気付いてなかったです(^^;


本来、値型は null という状態をとることはできません。C# の int も System.Int32 構造体のエイリアスなので、当然、値型です。なので表現できるのは整数値のみで null というのは表現できません。もし、値型も null を取れるようにすると値型の意味合いがかなり大きく変わってしまいます。しかし、そんなことをしなくても Generics を使えば 「null も表現できる値型」 が作れます。それが Nullable です。そして、C# では int? と型宣言をすると自動的に Nullable とコンパイルしてくれます(なので int? は単なるシンタックスシュガー)。


まぁ、以下のコードを見てもらえばわかるでしょう。


注意:某所の情報によると Nullable はなくなることはないと思いますが、int? が正式採用されるかどうかはまだ微妙みたいです。



int? i = null;
?
// 型名を表示(Nullable!1 とのこと)
Console.WriteLine(i.GetType().Name);
?
// null か確認
if (!i.HasValue)
{
    Console.WriteLine("!HasValue");
}
?
// null が確認
// ちなみになぜこれで動くかというと op_Implicit、すなわち implicit operator T (Nullable) が定義されているから。
if (i == null)
{
    Console.WriteLine("null");
}
?
// たとえ !HasValue であっても参照できる
// これも op_Implicit のおかげ。
if (i != 0)
{
    Console.WriteLine("i != 0");
}
?
// ただし !HasValue のときに Value を参照すると InvalidOperationException
//if (i.Value != 0)
//{
//    Console.WriteLine("i.Value != 0");
//}
?
// 整数を代入
i = 1;
?
// HasValue はもちろん true
Console.WriteLine(i.HasValue);
?
// i だけで参照。これも op_Implicit のおかげ。
Console.WriteLine("{0:d}", i);
Console.WriteLine(i.ToString());
?
// Value で参照
Console.WriteLine("{0:d}", i.Value);
Console.WriteLine(i.Value.ToString());

2004年5月18日火曜日

ASP.NET でクライアントサイドのエンターキーを制御する

IE では、テキストボックスが 1つとボタンが 1つといった場合に、テキストボックスでエンターキー(改行キー)を押すと自動的に submit してしまうため、PostBack が発生してしまいます。
こいつを PostBack させないようにする方法です。


/// <summary>
/// エンターキーを制御するクライアントスクリプトを出力します。
/// </summary>
/// <param name="page">スクリプトを出力する<see cref="System.Web.UI.Page"/>。</param>
public static void RegisterEnterKeyPageScript(System.Web.UI.Page page)
{
    page.RegisterClientScriptBlock("enterkey",
        "<script language='javascript'>\n" +
        "function text_keydown(e, name)\n" +
        "{\n" +
        "  var key = 0;\n" +
        "  if (typeof(e.keyCode) != 'undefined') {\n" +
        "    key = e.keyCode;\n" +
        "  } else if (typeof(e.which) != 'undefined') {\n" +
        "    key = e.which;\n" +
        "  }\n" +
        "  if (key == 0xd) {\n" +
        "    if (typeof(name) != 'undefined' && name != '') {\n" +
        "      document.forms[0].elements[name].click();\n" +
        "    }\n" +
        "    return false;\n" +
        "  }" +
        "  return true;" +
        "}" +
        "</script>");
}
 
 
/// <summary>
/// エンターキー押し下げ時にサブミットするボタンを設定します。
/// name が "" のときはエンターキーを無視します。
/// </summary>
/// <param name="control">設定する<see cref="System.Web.UI.WebControls.WebControl"/>。</param>
/// <param name="name">サブミットするボタンの name。</param>
public static void RegisterEnterKeyScript(System.Web.UI.WebControls.WebControl control, string name)
{
    control.Attributes["onkeydown"] = "return text_keydown(event, '" + name + "');";
}

まずはこんなメソッドをどこかに用意しといてください。
で、テキストボックスが TextBox1、ボタンが Button1 とすると、Page_Load イベントで


RegisterEnterKeyPageScript(this);
RegisterEnterKeyScript(TextBox1, "");

と呼び出してやればエンターキーが無効になるはずです。
また、


RegisterEnterKeyPageScript(this);
RegisterEnterKeyScript(TextBox1, "Button1");

としてやれば、テキストボックスでエンターキーを押すと Button1 をクリックしたことになるはずです。


"はず" なんて書いているのは、これらの動作は ASP.NET は関係なくて完全にクライアントのブラウザに依存するからです。実際、上記のメソッドはクライアントサイドの JavaScript を出力してるだけです。なので、JavaScript がオフにされてると上記のコードは動きません。それと、IE6 とと Netscape6 あたりなら動くと思いますが、他のブラウザはどうかわかりません。
(「こうしたほうがいいよ」 ということがあったらコメントでもつけてください)

2004年5月13日木曜日

.NET でシリアル通信を使う(覚え書き)

Whidbey では標準でサポートされますが、現状の .NET Framework 1.0、1.1 にはシリアル通信(シリアルポート(Serial Port)の RS-232C とかでモデムを繋いだりするやつのことね)のサポートがないんですよね。
といっても、Win32 ではシリアルポートってあまり特別な存在じゃなく、CreateFile して SetCommState でごにょごにょして、あとは WriteFile とか ReadFile とかして...って感じなので DllImport すれば .NET でだって使えるわけです。


と言っても、すでにそれらをラップして便利に使えるようにしてくれたソースがいろいろと公開されています。なので、それの覚え書き。
なお、以下はちょこっとソースを見ただけで、詳しく調べたわけじゃないのでコメントは間違ってるかもしれません。


MSDN Magazine 「Use P/Invoke to Develop a .NET Base Class Library for Serial Device Communications」
http://msdn.microsoft.com/msdnmag/issues/02/10/netserialcomm/

まぁ、標準的な実装なのかな?Win32 API をラップして使いやすくしたクラスが用意されてる。


The Code Project 「Serial Communications : The .NET Way」
http://www.codeproject.com/dotnet/DotNetComPorts.asp

こちらも上のと同じような感じかな?


GotDotNet User Sample 「SerialPort component and CSTerm terminal application」
http://www.gotdotnet.com/Community/UserSamples/Details.aspx?SampleGuid=b06e30f9-1301-4cc6-ac14-dfe325097c69

これは Form に貼り付けて使うという使い方ができるようになってるみたい。お手軽かも。


GotDotNet User Sample 「SerialStream - use the serial port as a Stream」
http://www.gotdotnet.com/Community/UserSamples/Details.aspx?SampleGuid=FCBA7FC5-666E-4EB0-863F-0045B0C79EC7

おっ、これはおもしろいかも。Stream を継承して SerialStream を作ってある。ちゃんと BeginRead/Write などの非同期メソッドもある。

2004年5月7日金曜日

.Text から PING.BLOGGERS.JP さんにも ping を送るようにする

もともと .Text では http://www.weblogs.com/ に ping を送る(※1)ようになっています。(web.config でオフにすることもできます)
ちなみに、http://www.weblogs.com/ を IE6 で見ると日本語が文字化けしてますが、「表示」-「エンコード」 メニューで utf-8 を選択すればそれなりに見えるようになります。


※1 プロトコルの仕様はこちら。Weblogs.Com XML-RPC interface


で、この処理を行っているのは Dottext.Framework\Tracking\WeblogsNotificatinProxy.cs なんですが、実装方法がちょっと変わっています。Attribute で送信先 URL や Method を指定するようになっています。これは XML-RPC.NET の CookComputing.XmlRpc.dll を使って実装しているようです。


というわけで 「WeblogsNotificatinProxy.cs をまねして http://ping.bloggers.jp/rpc/ に ping を送るクラスを作る」 というのが一番楽そうだったのでそうしてみました。


追加・変更したソースを http://www.divakk.co.jp/aoyagi/BloggersJpNotificatinProxy.ZIP においておきます。
BloggersJpNotificatinProxy.cs (と .resx)が WeblogsNotificatinProxy.cs をまねして新規に作ったクラスです。
Notification.cs は 3行だけ追加してあります。
これらの追加・変更を行ってビルドすれば PING.BLOGGERS.JP にも ping を送るようになります。


一応、ビルドした DLL を http://www.divakk.co.jp/aoyagi/dotText_bin.ZIP においておきます。この DLL は、私のところで動いているものと同じですので Trackback ping の utf-8 化などの修正も行ってあるものです。

2004年5月6日木曜日

PING.BLOGGERS.JP さんに ping を送ってみる

PING.BLOGGERS.JP さんに ping を送るようにしてみました。


が、これであってるのかどうか今ひとつ自信がありません。ちゃんとできているようなら改造方法を公開します。(ソースを改造してビルドしなおさないとダメなんですが)

.Text のインラインコメント化

.Text のインラインコメント表示についてです。
(インラインコメントっていうのは私が勝手にそう呼んでるだけです。ここでやってるように各 Post の下にコメントやトラックバックも表示することをそう呼んでます)


原水商店さんの .Text Blogs 日本語 Skin から頂いたスキンをインラインコメント化したものを置いておきます。
http://www.divakk.co.jp/aoyagi/SkinsJP_IC.zip


インラインコメント化スキンの使用方法



  1. InlineComments.cs を Skins フォルダにコピーしてください。
  2. 各スキンを Skins フォルダにコピーしてください。インラインコメント化したスキンはスキン名(スキンのフォルダ名)の末尾に "_IC" をつけてありますので、従来のスキンと重なることはありません。
  3. Admin\Skins.config ファイルを適当に変更してください。サンプルを同梱してあります。なお、同梱した Skins.config は .Text Blogs 日本語 Skin とインラインコメント化スキンをあわせて使った場合の config になっています。こうしておくと普通のスキンとインラインコメント化したスキンのどちらでも選べるようになります。






以下に簡単ですがインラインコメント化する方法を書いておきます。
(簡単というよりほとんど覚え書きのような状態ですが)


InlineComments.cs を Skins フォルダにコピー。
(ソースコードによるコードビハインド。ソースコードにしたのは DLL を作り直さなくてもいいようにするため)


各スキンのインラインコメント化



  1. Comments.ascx をコピーして InlineComments.ascx を作る。
  2. InlineComments.ascx の 1行目の Inherits="Dottext.Web.UI.Controls.Comments" をInherits="Dottext.Web.UI.Controls.InlineComments" に変更。また、Src="..\..\InlineComments.cs" を追加。
  3. Day.ascx に <%@ Register TagPrefix="uc1" TagName="InlineComments" Src="InlineComments.ascx" %>を追加。<%@ Import Namespace = "Dottext.Framework.Components" %> を追加。適当な場所に を追加(CommentDisplayCount で最大いくつのコメントをインライン表示するか設定可能)。

これで一応は動くはず。
あとは見栄えがよくなるように InlineComments.ascx を修正する。
たとえば




  • <a name = "feedback" /> を削除。


  • <h3>フィードバック</h3> を削除。


  • <div id="comments"> を <div class="inlinecomments"> に変更。


  • <asp:Literal ID = "NoCommentMessage" Runat ="server" /> を削除。


  • HeaderTemplate を追加して見出しを表示。


  • ToTrackbackText を追加してトラックバックかどうかを表示するようにする(このために <%@ Import Namespace = "Dottext.Framework.Components" %> を追加する必要あり)。

など。
その上で Style.css に適当な CSS を追加。