C#と諸々

C#がメインで他もまぁ諸々なブログです
おかしなこと書いてたら指摘してくれると嬉しいです(´・∀・`)
つーかコメント欲しい(´・ω・`)

2009/11/10 01:48
約4ヶ月ぶりの更新です。
しぶとく生きてます。
最近は C# 触れてないです。
RSS フィードも未読が 2000 件くらいあって読む気がしません。
まるで虐待です。
まぁそんなことはいいとして、これからはもう少しまともに更新していきたいと思っています。でも思っているだけです。たぶんまだしばらくはあまり更新できません、ごめんなさい。
タグ:
2009/06/30 01:13
突然ですが、アフィリエイトを始めることにしました。近々サイドバーにウィジェットを配置する予定ですが、まずは最近気になっているこの本をここでご紹介したいと思います。

テストコードの用意されていないコードは全てレガシーコードと呼ぶそうです。(なので新規開発でもテストコードが用意されていなければレガシーコードになります。)
レガシーコードに手を入れる時は、手を入れる箇所 (と周辺のコード) にテストコードを用意しリファクタリングを行うと良い、という話はよく聞きますが、そうは言っても具体的にはどのようにテスト可能なコードに導いていけば良いのか、どの程度まで足を踏み込んで良いのか等、悩みの種はたくさんです。
しかし、本書を読めばきっとそういう悩みが解決されるだろうと僕は勝手に予想しています。これでレガシーコードも余裕です。

ちなみに Amazon には発売日がまだ表示されていないようですが、 (←勘違いだったようです) 発売日は 7/14 らしいです。
2009/06/29 19:47
マスターページ内の link タグの href 属性では、チルダ (~) を使った仮想パス形式、もしくはマスターページの配置場所からの相対パス形式で記述しておくと、実行時に適切な相対パスに変換してくれます。(追記:head タグに runat="server" を記述していない場合は変換されませんので注意してください。)
しかし、script タグの src 属性に関しては、チルダを使った仮想パスや相対パスで記述しても変換が一切行われません。
なので、Control.ResolveClientUrl メソッドVirtualPathUtility.ToAbsolute メソッドを使用して変換する必要があります。幸い、HTML タグの属性値ならば <%= %> が使用できるので (コードのハイライトやインテリセンスは効きませんが) 簡単に対処できます。

Site.Master
<head runat="server">
    <title><asp:Localize runat="server" Text="<%$ Resources:CommonResource, SystemName %>" /></title>
    <link href="Common.css" type="text/css" rel="stylesheet" />
    <link href="Site.css"   type="text/css" rel="stylesheet" />
    <script src="<%= this.ResolveClientUrl("~/Common.js") %>" type="text/javascript"></script>
    <script src="<%= this.ResolveClientUrl("~/Site.js") %>"   type="text/javascript"></script>
    <asp:ContentPlaceHolder ID="HeadPlaceHolder" runat="server" />
</head>


なお、スタイルシートに関しては Thema 機能を使用すれば link タグを記述する必要はなくなりますが、全てのスタイルシートが読み込まれてしまうため、(スタイルシートの) クラス名の衝突の回避に一工夫必要だったりと管理が複雑化します。テーマの切り替えが不要ならば使用しない方が良いかと思います。


[関連]
C#と諸々 ルートディレクトリを示す ~ 演算子
タグ: .NET C# ASP.NET
2009/06/24 09:36
今まで何も考えず複数形を基本にしてたけど、ホントは適切に使い分けないといけないんだよね。
ドメインレイヤで集約毎に名前空間を切る時、今まではエンティティ (集約ルート) の名前を複数形にしてたんだけど、これも不適切だなぁ。例えば Book というエンティティは Hoge.Fuga.Domains.Books という名前空間に。
# Domains も Domain の方が適切だ ^^;

別に Book が数種類あるわけでもないのに Books というのはおかしな話。でも、かといって単数形で Book にしちゃうとクラス名とかぶってしまうわけで…。
この名前空間は Book の集約を含めるための名前空間だから BookAggregate が妥当なのかなー。それとも、そこまで気にしないで Books にしちゃうか…。
タグ:
2009/06/15 01:33
bleis-tift さんが前に言ってた、D 言語の強い typedef が C# にも欲しいなぁです。
まぁ無いものはしょうがないってことで、お遊びでこんなクラス作ってみました。

Int32Def(TSelf).cs
using System;
using System.Runtime.Serialization;
using System.Reflection;

public abstract class Int32Def<TSelf>
    where TSelf : Int32Def<TSelf>
{
    private readonly int _value;

    public static implicit operator int(Int32Def<TSelf> value)
    {
        return value._value;
    }

    public static explicit operator Int32Def<TSelf>(int value)
    {
        TSelf obj = (TSelf)FormatterServices.GetUninitializedObject(typeof(TSelf));
        FieldInfo valueField = typeof(Int32Def<TSelf>).GetField("_value", BindingFlags.NonPublic | BindingFlags.Instance);
        valueField.SetValue(obj, value);
        return obj;
    }

    public static TSelf operator +(Int32Def<TSelf> value)
    {
        return (TSelf)(+value._value);
    }

    public static TSelf operator -(Int32Def<TSelf> value)
    {
        return (TSelf)(-value._value);
    }

    public static TSelf operator ~(Int32Def<TSelf> value)
    {
        return (TSelf)(~value._value);
    }

    public static TSelf operator ++(Int32Def<TSelf> value)
    {
        int temp = value._value;
        temp++;
        return (TSelf)(temp);
    }

    public static TSelf operator --(Int32Def<TSelf> value)
    {
        int temp = value._value;
        temp--;
        return (TSelf)(temp);
    }

    public static TSelf operator +(Int32Def<TSelf> value1, Int32Def<TSelf> value2)
    {
        return (TSelf)(value1._value + value2._value);
    }

    public static TSelf operator -(Int32Def<TSelf> value1, Int32Def<TSelf> value2)
    {
        return (TSelf)(value1._value - value2._value);
    }

    public static TSelf operator *(Int32Def<TSelf> value1, Int32Def<TSelf> value2)
    {
        return (TSelf)(value1._value * value2._value);
    }

    public static TSelf operator /(Int32Def<TSelf> value1, Int32Def<TSelf> value2)
    {
        return (TSelf)(value1._value / value2._value);
    }

    public static TSelf operator %(Int32Def<TSelf> value1, Int32Def<TSelf> value2)
    {
        return (TSelf)(value1._value % value2._value);
    }

    public static TSelf operator &(Int32Def<TSelf> value1, Int32Def<TSelf> value2)
    {
        return (TSelf)(value1._value & value2._value);
    }

    public static TSelf operator |(Int32Def<TSelf> value1, Int32Def<TSelf> value2)
    {
        return (TSelf)(value1._value | value2._value);
    }

    public static TSelf operator ^(Int32Def<TSelf> value1, Int32Def<TSelf> value2)
    {
        return (TSelf)(value1._value ^ value2._value);
    }

    public static TSelf operator <<(Int32Def<TSelf> value1, int value2)
    {
        return (TSelf)(value1._value << value2);
    }

    public static TSelf operator >>(Int32Def<TSelf> value1, int value2)
    {
        return (TSelf)(value1._value >> value2);
    }
}


Program.cs
using System;

class Hoge : Int32Def<Hoge>
{
}

class Fuga : Int32Def<Fuga>
{
}

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(Test((Hoge)5, (Hoge)10)); //=> 15
        Console.WriteLine(Test((Fuga)5, (Fuga)10)); //=> 50
    }

    static Hoge Test(Hoge a, Hoge b)
    {
        return a + b;
    }

    static Fuga Test(Fuga a, Fuga b)
    {
        return a * b;
    }
}



あくまでもお遊びです。Int32 限定ですし、構造体ではなくクラス (従って null がありえますし現時点では対策してません) です。あと、演算子しか考慮してません。

ちなみに T4 Template 版もあります。まだ詰めが甘いですが。こちらは構造体としてコード生成するので、null を許容しません。あと、Int32 以外のプリミティブ型もたぶん行けます、たぶん。
こっちはもうちょい頑張れば実用的なものにできるかなと思います。

<#@ template language="C#" #>
<#@ output extension=".cs" #>
<#
    string namespaceName = "Samples";
    string newTypeName = "Hoge";
    string sourceTypeName = "int";
   
    string[] unaryOperators = new string[]
    {
        "+",
        "-",
        "~",
        //"!",
    };
   
    string[] destructiveUnaryOperators = new string[]
    {
        "++",
        "--",
    };
   
    string[] binaryOperators = new string[]
    {
        "+",
        "-",
        "*",
        "/",
        "%",
        "&",
        "|",
        "^",
    };
   
    string[] booleanOperators = new string[]
    {
        "true",
        "false"
    };
   
    string[] shiftOperators = new string[]
    {
        "<<",
        ">>"
    };
   
    string[] comparisonOperators = new string[]
    {
        "==",
        "!=",
        "<",
        ">",
        "<=",
        ">="
    };
#>
namespace <#= namespaceName #>
{
    public struct <#= newTypeName #>
    {
        public <#= newTypeName #>(<#= sourceTypeName #> value)
        {
            this._value = value;
        }
       
        private readonly <#= sourceTypeName #> _value;
       
        public static implicit operator <#= sourceTypeName #>(<#= newTypeName #> value)
        {
            return value._value;
        }
       
        public static explicit operator <#= newTypeName #>(<#= sourceTypeName #> value)
        {
            return new <#= newTypeName #>(value);
        }
<#
    foreach (string unaryOperator in unaryOperators)
    {
#>

        public static <#= newTypeName #> operator <#= unaryOperator #>(<#= newTypeName #> value)
        {
            return new <#= newTypeName #>(<#= unaryOperator #>value._value);
        }
<#
    }
#>
<#
    foreach (string destructiveUnaryOperator in destructiveUnaryOperators)
    {
#>

        public static <#= newTypeName #> operator <#= destructiveUnaryOperator #>(<#= newTypeName #> value)
        {
            <#= sourceTypeName #> temp = value._value;
            temp<#= destructiveUnaryOperator #>;
            return new <#= newTypeName #>(temp);
        }
<#
    }
#>
<#
    foreach (string binaryOperator in binaryOperators)
    {
#>

        public static <#= newTypeName #> operator <#= binaryOperator #>(<#= newTypeName #> value1, <#= newTypeName #> value2)
        {
            return new <#= newTypeName #>(value1._value <#= binaryOperator #> value2._value);
        }
<#
    }
#>
<#
    foreach (string shiftOperator in shiftOperators)
    {
#>

        public static <#= newTypeName #> operator <#= shiftOperator #>(<#= newTypeName #> value1, int value2)
        {
            return new <#= newTypeName #>(value1._value <#= shiftOperator #> value2);
        }
<#
    }
#>
<#
/*
    foreach (string booleanOperator in booleanOperators)
    {
#>

        public static bool operator <#= booleanOperator #>(<#= newTypeName #> value)
        {
            throw new System.NotImplementedException();
        }
<#
    }
*/
#>
    }
}