裏口からのC#実践入門

昨日の更新忘れと一緒に。

1-24 別の名前空間での同じ名前の多用

こんな書き方ができるとは。
ただ、まぁわかりづらいと思うので避けた方が良い気がする。

using System;
using FPath = System.IO.Path;

namespace Uraguchi
{
    public class Tenshi24
    {
        public static void Run()
        {
            var fullPath = FPath.Combine("C://A", "B.txt");
            Console.WriteLine(fullPath);
        }
    }
}

1-25 多すぎる引数

テンシちゃんの言う通り、本来ならツリー構造にするか、もしくはBuilderパターンを使うのが良いのかな。
この解決方法は書籍の通り、「少ない手間で乗り切る知恵」であって、最初からこんな引数モリモリならダメ。
今回はデフォルト引数、名前付き引数で解決している。

  • ラマくん
using System;

namespace Uraguchi.Scene1
{
    public class Blama25
    {
        class Person
        {
        }

        private static void dumpPersons(
            Person 自分, Person 父, Person 母,
            Person 父方の祖父, Person 父方の祖母,
            Person 母方の祖父, Person 母方の祖母,
            Person 子1, Person 子2, Person 子3,
            Person 孫1, Person 孫2, Person 孫3
        )
        {
        }

        public static void Run()
        {
            var 親もなければ子もないオレ = new Person();
            dumpPersons(
                親もなければ子もないオレ, null, null, null, null,
                null, null, null, null, null, null, null, null
            );
        }
    }
}
  • テンシちゃん
using System;

namespace Uraguchi.Scene1
{
    public class Tenshi25
    {
        class Person
        {
        }

        private static void dumpPersons(
            Person 自分 = null, Person 父 = null, Person 母 = null,
            Person 父方の祖父 = null, Person 父方の祖母 = null,
            Person 母方の祖父 = null, Person 母方の祖母 = null,
            Person 子1 = null, Person 子2 = null, Person 子3 = null,
            Person 孫1 = null, Person 孫2 = null, Person 孫3 = null
        )
        {
        }

        public static void Run()
        {
            var 親もなければ子もないオレ = new Person();
            var 子供 = new Person();
            dumpPersons(親もなければ子もないオレ, 子1: 子供);
        }
    }
}

1-26 付けすぎる virtual

使い方によってはアクマくんのようにProduct側に計算式を直書きするのもあり。
テンシちゃんの方法は、使う側で決めよう、という方式。
ケースバイケースかなぁ。
デリゲート型を使う。
Func(T, TResult) デリゲート (System)

using System;

namespace Uraguchi
{
    public class Tenshi26Product
    {
        private Func<int, int> exp;

        public int CalcPrice(int basePrice)
        {
            return exp(basePrice);
        }

        public Tenshi26Product(Func<int, int> exp)
        {
            this.exp = exp;
        }
    }

    public class Tenshi26
    {
        public static void Run()
        {
            Tenshi26Product product = new Tenshi26Product(n => n * 8 / 10);
            Console.WriteLine(product.CalcPrice(100));
        }
    }
}

1-27 ソースコードにパスワードを直書きする

パスワードはプロパティファイルにでも書いとこう、と言う話だが、Monoだとプロパティファイルを作成、読み取りする簡単な仕組みがなさそう?

Can I set Properties.Settings.Default.VariableName = Some_value in Mono under linux? - Stack Overflow

1-28 例外を処理しないのに catch する

基本的には例外はそのまま発生させる、と。
例外についてはどういう設計思考でやるか決めてからにしないと、おかしなところで握りつぶされてしまって意図しない動作となることがある。
例外が発生することが前提であるなら、それは例外ではなくて条件の一つである。

using System;

namespace Uraguchi.Scene1
{
    public class Tenshi28
    {
        public static void Run()
        {
            int y;
            // string x = "0x123";
            string x = "ZZZ";
            int.TryParse(x, out y);
            Console.WriteLine(y);
        }
    }
}

1-29 catch して何もせずそのまま throw する

不要なコードは負債なので削る必要がある。
上に伝える前に処理したいことを処理して throw することによりそのまま投げる。

using System;

namespace Uraguchi.Scene1
{
    public class Blama29
    {
        public static void Run1(string[] args)
        {
            try
            {
                if (args.Length == 0)
                    throw new ArgumentException("王様の耳はロバの耳");
            }
            catch (Exception)
            {
                throw;
            }
        }

        public static void Run2(string[] args)
        {
            if (args.Length == 0)
                throw new ArgumentException("王様の耳はロバの耳");
        }
    }
}

1-30 何の役割もない継承を繰り返す

Createをそのまま利用するのでFactoryっぽくなってる。
不要な継承はなくす。必要になったタイミングで、必要なことを。
YAGNI - Wikipedia
KISSの原則 - Wikipedia

using System;

namespace Uraguchi.Scene1
{
    public class イエイヌ
    {
        public static イエイヌ Create()
        {
            return new イエイヌ();
        }

        public void お座り()
        {
            Console.WriteLine("くぅーん");
        }
    }

    public class Tenshi30
    {
        public static void Run()
        {
            var dog = イエイヌ.Create();
            dog.お座り();
        }
    }
}