カテゴリー
C

独習C#第3版、P482 型パラメータの制約、基本クラス制約

using System;

namespace Chapter01All
{
    class MyStrMethods2
    {
        public string ReverseStr(string str)
        {
            string w = "";
            for( int i=0; i<str.Length; i++)
            {
                w = str[i] + w;
            }
            return w;
        }
    }
    class Test<T> where T : MyStrMethods2
    {
        T obj;
        public Test( T o)
        {
            obj = o;
        }
        public void ShowReverse(string str)
        {
            string w = obj.ReverseStr(str);
            Console.WriteLine(w);
        }
    }
    class Demo
    {
        static void Main()
        {
            MyStrMethods2 objA = new MyStrMethods2();
            Test<MyStrMethods2> t1 = new Test<MyStrMethods2>(objA);
            t1.ShowReverse("This is a test.");
        }
    }
}

基本クラス制約は、型パラメータに当てはめる型(つまり、型引数)が、特定の型から継承しなけらばならないという制限を加えるものです。上の例ではclass Testはclass MyStrMethods2を継承していることを制限するということですかね。それをwhere T : MyStrMethods2と書く、ということですか?

using System;

namespace Chapter01All
{
    class MyStrMethods2
    {
        public string ReverseStr(string str)
        {
            string w = "";
            for( int i=0; i<str.Length; i++)
            {
                w = str[i] + w;
            }
            return w;
        }
    }
    class Test<T> where T : MyStrMethods2
    {
        T obj;
        public Test( T o)
        {
            obj = o;
        }
        public void ShowReverse(string str)
        {
            string w = obj.ReverseStr(str);
            Console.WriteLine(w);
        }
    }
    class MyClass : MyStrMethods2 { }
    class Demo
    {
        static void Main()
        {
            MyStrMethods2 objA = new MyStrMethods2();
            Test<MyStrMethods2> t1 = new Test<MyStrMethods2>(objA);
            t1.ShowReverse("This is a test.");

            MyClass objB = new MyClass();
            Test<MyClass> t2 = new Test<MyClass>(objB);
            t2.ShowReverse("This is a test,too.");
        }
    }
}

class Demoの後半部分が追加になってます。継承の仕方が最初の例と後半で少し違います。

using System;

namespace Chapter01All
{
    class MyStrMethods3
    {
        string str;
        public MyStrMethods3(string Str = "default string")
        {
            str = Str;
        }
        
        public void ShowReverse()
        {
            Console.WriteLine(ReverseStr());
        }
        public string ReverseStr()
        {
            string w = "";
            for (int i = 0; i < str.Length; i++)
            {
                w = str[i] + w;
            }
            return w;
        }
    }
 
    class MyClass : MyStrMethods3 { }
    class Demo
    {
        static void Main()
        {
            MyStrMethods3 objA = new MyStrMethods3("This is a test.");
            objA.ShowReverse();
           

            MyClass objB = new MyClass();
            objB.ShowReverse();
            
        }
    }
}

 面倒なことを止めて、基本だったら、こうでしょう。ReverseStrのアクセス修飾子がpublicになってますが、privateで問題ないと思います。

カテゴリー
C

C#、ジェネリッククラスに演算子オーバーロードを使ってみました。

using System;

namespace Chapter01All
{
    class GenericClassDemo2
    {
        public static void Main()
        {
            var testClass1 = new TestClass<int>(20, 30);
            Console.WriteLine(testClass1.GetAns);

            var testClass2 = new TestClass<int>(200, 300);
            Console.WriteLine(testClass2.GetAns);

            var testClass3 = new TestClass<int>();
            testClass3 = testClass1 + testClass2;
            Console.WriteLine(testClass3.GetAns);
        }
    }
}

namespace Chapter01All
{

    class TestClass<T>
    {
        T a;
        T b;
        T ans;
        public TestClass(T x , T y)
        {
            a = x;
            b = y;
            ans = (dynamic)a + (dynamic)b;
        }
        public TestClass()
        {
            a = (dynamic)0;
            b = (dynamic)0;
            ans = (dynamic)0;
        }
        public T Seta {
            set
            {
                a = value;
            }
        }
        public T Setb
        {
            set
            {
                b = value;
            }
        }
        public T GetAns {
            get{
                return (dynamic)ans;
            }
        }
        public void MakeAns()
        {
            ans = (dynamic)a + (dynamic)b;
        }
        public TestClass<T> CreateAns(TestClass<T> that)
        {
            var testClass = new TestClass<T>();
            testClass.a = (dynamic)this.a + (dynamic)that.a;
            testClass.b = (dynamic)this.b + (dynamic)that.b;
            testClass.ans = (dynamic)this.ans + (dynamic)that.ans;
            return testClass;
        }

        public static TestClass<T> operator +(TestClass<T> kariobj, TestClass<T> kari)
        {
            var testClass = new TestClass<T>();
            var myGeneric = kariobj.CreateAns(kari);
            return myGeneric;
        }
    }
}

何に使えるかと言うと分かりませんが、頭の体操というか?混乱のもと作り?

カテゴリー
C

C#,ジェネリック型のクラスのdynamicを使った演算、デフォルトコンストラクターとプロパティを使ってみました。

using System;

namespace Chapter01All
{
    class GenericClassDemo2
    {
        public static void Main()
        {
            var testClass1 = new TestClass<int>(20, 30);
            Console.WriteLine(testClass1.GetAns);

            var testClass2 = new TestClass<double>(200.2, 300.3);
            Console.WriteLine(testClass2.GetAns);

            var testClass3 = new TestClass<int>();
            testClass3.Seta = 10;
            testClass3.Setb = 20;
            testClass3.MakeAns();
            Console.WriteLine(testClass3.GetAns);
        }
    }
}

namespace Chapter01All
{

    class TestClass<T>
    {
        T a;
        T b;
        T ans;
        public TestClass(T x , T y)
        {
            a = x;
            b = y;
            ans = (dynamic)a + (dynamic)b;
        }
        public TestClass()
        {
            a = (dynamic)0;
            b = (dynamic)0;
            ans = (dynamic)0;
        }
        public T Seta {
            set
            {
                a = value;
            }
        }
        public T Setb
        {
            set
            {
                b = value;
            }
        }
        public T GetAns {
            get{
                return (dynamic)ans;
            }
        }
        public void MakeAns()
        {
            ans = (dynamic)a + (dynamic)b;
        }
    }
}

MakeAnsが復活しました。

カテゴリー
C

C#、ジェック型クラスのdynamicを使った演算

using System;

namespace Chapter01All
{
    class GenericDemo
    {
        public static void Main()
        {
            var testClass1 = new TestClass<int>(20, 30);
            testClass1.MakeAddWithDynamic();
            Console.WriteLine(testClass1.GetAns());

            var testClass2 = new TestClass<double>(200.2, 300.3);
            testClass2.MakeAddWithDynamic();
            Console.WriteLine(testClass2.GetAns());
        }
    }

    class TestClass<T>
    {
        T a;
        T b;
        T ans;
        public TestClass(T x, T y)
        {
            a = x;
            b = y;
        }
        public void MakeAddWithDynamic()
        {
            ans = (dynamic)a + (dynamic)b;
        }
        public T GetAns()
        {
            return (dynamic)ans;
        }
    }
}

ネットから拾ったサンプルが複雑でした。今のとこ、理解できないので、より簡単そうな形式(dynamic)を使った方にまとめました。正確にはつかんでませんが。上の例は、複素数のクラスの例に近いように思います。ansの計算だけを変えれば、そのままではないでしょうか?

using System;

namespace Chapter01All
{
    class GenericClassDemo2
    {
        public static void Main()
        {
            var testClass1 = new TestClass<int>(20, 30);
            Console.WriteLine(testClass1.GetAns);

            var testClass2 = new TestClass<double>(200.2, 300.3);
            Console.WriteLine(testClass2.GetAns);
        }
    }
}

namespace Chapter01All
{

    class TestClass<T>
    {
        T a;
        T b;
        T ans;
        public TestClass(T x, T y)
        {
            a = x;
            b = y;
            ans = (dynamic)a + (dynamic)b;
        }
        public T GetAns {
            get{
                return (dynamic)ans;
            }
        }
    }
}

GetAnsをプロパティに変えてみました。GetAnsはコンストラクターに入れました。a,bが決まれば、ansも決まります。ちなみに望洋先生のC++入門、では複素数クラスなのでansは在りません。

カテゴリー
C

C#、ジェック型クラスに演算子オーバーロードして見ましたが、四苦八苦しました。

using System;
using System.Linq;

namespace Chapter01All
{   
    class MyGeneric<T>
    {
        public T num1;
        public MyGeneric(T obj1)
        {
            num1 = obj1;
        }
        public T GetNum1()
        {
            return num1;
        }
        public static MyGeneric<T> operator +(MyGeneric<T> kariobj, MyGeneric<T> kari)
        {
            var testClass = new TestClass<T>();
            var myGeneric = new MyGeneric<T>(testClass.AddWithDynamic(kariobj.num1, kari.num1));
            return myGeneric;
        }
    }
    public class GenericOperation<T>
    {
        public GenericOperation()
        {
            var availableT = new Type[]
            {
                typeof(int), typeof(uint), typeof(short), typeof(ushort),
                typeof(long), typeof(ulong), typeof(byte),
                typeof(decimal), typeof(double)
            };
            if (!availableT.Contains(typeof(T)))
                {
                    throw new NotSupportedException();
                }
        }
    }
 
    class TestClass<T>
    {
        public T AddWithDynamic(T a, T b)
        {
            return (dynamic)a + (dynamic)b;
        }
    }
    
    class GenericDemo
    {
        static void Main()
        {
            MyGeneric<int> intobj = new MyGeneric<int>(100);
            MyGeneric<int> intobj2 = new MyGeneric<int>(200);
            MyGeneric<int> ans = intobj + intobj2;
            Console.WriteLine(ans.GetNum1());

            MyGeneric<double> intobj3 = new MyGeneric<double>(1.2345);
            MyGeneric<double> intobj4 = new MyGeneric<double>(10.0001);
            MyGeneric<double> ans2 = intobj3 + intobj4;
            Console.WriteLine(ans2.GetNum1());

        }
    }
}

実行画面は省略しますが、intとdoubleで上手く行ったので、良いんだろうと思います。まあ、面倒ですね。

using System;
using System.Linq;
using System.Linq.Expressions;

namespace Chapter01All
{   
    class MyGeneric<T>
    {
        public T num1;
        public MyGeneric(T obj1)
        {
            num1 = obj1;
        }
        public T GetNum1()
        {
            return num1;
        }
        public static MyGeneric<T> operator +(MyGeneric<T> kariobj, MyGeneric<T> kari)
        {
            var testClass = new TestClass<T>();
            var myGeneric = new MyGeneric<T>(testClass.AddWithDynamic(kariobj.num1, kari.num1));
            return myGeneric;
        }
    }
    public class GenericOperation<T>
    {
        public GenericOperation()
        {
            var availableT = new Type[]
            {
                typeof(int), typeof(uint), typeof(short), typeof(ushort),
                typeof(long), typeof(ulong), typeof(byte),
                typeof(decimal), typeof(double)
            };
            if (!availableT.Contains(typeof(T)))
                {
                    throw new NotSupportedException();
                }
            var p1 = Expression.Parameter(typeof(T));
            var p2 = Expression.Parameter(typeof(T));
            Add = Expression.Lambda<Func<T, T, T>>(Expression.Add(p1, p2), p1, p2).Compile();
            Subtract = Expression.Lambda<Func<T, T, T>>(Expression.Subtract(p1, p2), p1, p2).Compile();
            Multiply = Expression.Lambda<Func<T, T, T>>(Expression.Multiply(p1, p2), p1, p2).Compile();
            Divide = Expression.Lambda<Func<T, T, T>>(Expression.Divide(p1, p2), p1, p2).Compile();
            Modulo = Expression.Lambda<Func<T, T, T>>(Expression.Modulo(p1, p2), p1, p2).Compile();
            Equal = Expression.Lambda<Func<T, T, bool>>(Expression.Equal(p1, p2), p1, p2).Compile();
            GreaterThan = Expression.Lambda<Func<T, T, bool>>(Expression.GreaterThan(p1, p2), p1, p2).Compile();
            GreaterThanOrEqual = Expression.Lambda<Func<T, T, bool>>(Expression.GreaterThanOrEqual(p1, p2), p1, p2).Compile();
            LessThan = Expression.Lambda<Func<T, T, bool>>(Expression.LessThan(p1, p2), p1, p2).Compile();
            LessThanOrEqual = Expression.Lambda<Func<T, T, bool>>(Expression.LessThanOrEqual(p1, p2), p1, p2).Compile();

        }
        public Func<T, T, T> Add { get; private set; }
        public Func<T, T, T> Subtract { get; private set; }
        public Func<T, T, T> Multiply { get; private set; }
        public Func<T, T, T> Divide { get; private set; }
        public Func<T, T, T> Modulo { get; private set; }
        public Func<T, T, bool> Equal { get; private set; }
        public Func<T, T, bool> GreaterThan { get; private set; }
        public Func<T, T, bool> GreaterThanOrEqual { get; private set; }
        public Func<T, T, bool> LessThan { get; private set; }
        public Func<T, T, bool> LessThanOrEqual { get; private set; }

    }

    class TestClass<T>
    {
        public T AddWithDynamic(T a, T b)
        {
            return (dynamic)a + (dynamic)b;
        }
    }
    
    class GenericDemo
    {
        static void Main()
        {
            MyGeneric<int> intobj = new MyGeneric<int>(100);
            MyGeneric<int> intobj2 = new MyGeneric<int>(200);
            MyGeneric<int> ans = intobj + intobj2;
            Console.WriteLine(ans.GetNum1());

            MyGeneric<double> intobj3 = new MyGeneric<double>(1.2345);
            MyGeneric<double> intobj4 = new MyGeneric<double>(10.0001);
            MyGeneric<double> ans2 = intobj3 + intobj4;
            Console.WriteLine(ans2.GetNum1());

        }
    }
}

 class GenericOperationについては、拝借したので、どうやって使うのかも分かりません。少し調べてみようと思います。Expressionについてはエラーを回避する方法が分かりました。using System.linq.Expression;を入れてやればエラー出ません。内容については、苦手なラムダ式と関係してるようです。”(-“”-)”

カテゴリー
C

C#ジェネリック型の演算は難しいようです。

using System;
using System.Linq;

namespace Chapter01All
{
    class MyGeneric<T>
    {
        T num1;
        T num2;
        T ans;
        public MyGeneric(T obj1, T obj2)
        {
            num1 = obj1;
            num2 = obj2;
        }
        public T GetNum1()
        {
            return num1;
        }
        public T GetNum2()
        {
            return num2;
        }
        public T GetAns()
        {
            return ans;
        }
        public void Add()
        {
            var testClass = new TestClass<T>();
            ans = testClass.AddWithDynamic(num1, num2);
            //ans = num1 + num2;と書きたいところ
        }
    }
    public class GenericOperation<T>
    {
        public GenericOperation()
        {
            var availableT = new Type[]
            {
            typeof(int), typeof(uint), typeof(short), typeof(ushort), typeof(long), typeof(ulong), typeof(byte),
            typeof(decimal), typeof(double)
            };
            if (!availableT.Contains(typeof(T)))
            {
                throw new NotSupportedException();
            }
        }
/*      //public T AddWithExpressionTree(T a, T b)を使わなければ、コメントアウトで構わないようです。
                public Func<T, T, T> Add { get; private set; }
                public Func<T, T, T> Subtract { get; private set; }
                public Func<T, T, T> Multiply { get; private set; }
                public Func<T, T, T> Divide { get; private set; }
                public Func<T, T, T> Modulo { get; private set; }
                public Func<T, T, bool> Equal { get; private set; }
                public Func<T, T, bool> GreaterThan { get; private set; }
                public Func<T, T, bool> GreaterThanOrEqual { get; private set; }
                public Func<T, T, bool> LessThan { get; private set; }
                public Func<T, T, bool> LessThanOrEqual { get; private set; }
*/
    }
    class TestClass<T>
    {
//        private GenericOperation<T> go = new GenericOperation<T>();
        public T AddWithDynamic(T a, T b)
        {
            return (dynamic)a + (dynamic)b;
        }
/*
        public T AddWithExpressionTree(T a, T b)
        {
            return go.Add(a, b);
        }
*/
    }
class GenericSampleDemo
    {
        static void Main()
        {
            MyGeneric<int> iOb;
            iOb = new MyGeneric<int>(100,200);
            Console.WriteLine(iOb.GetNum1());
            Console.WriteLine(iOb.GetNum2());
            iOb.Add();
            Console.WriteLine(iOb.GetAns());

            MyGeneric<double> iOb2;
            iOb2 = new MyGeneric<double>(100.1, 200.2);
            Console.WriteLine(iOb2.GetNum1());
            Console.WriteLine(iOb2.GetNum2());
            iOb2.Add();
            Console.WriteLine(iOb2.GetAns());
        }
    }
}

dynamicを使うことで、結構簡単になるようですが、varというキーワードを使ってるようですが、計算だけなら、そもそもvarだけで行けませんか?少しだけ調べると、初期がされる場合に使えるキーワードのようです。var num1 = 100;とかくとnum1はintとして扱われる。

カテゴリー
C

ジェネリック型の加算は、難しい?

using System;
using System.Linq;

namespace Chapter01All
{
 
    class GenericDemo
    {
        static void Main()
        {     
            var testClass = new TestClass<int>();
            int a = 100; int b = 200;
            Console.WriteLine( testClass.AddWithDynamic(a, b));

            var testClass2 = new TestClass<double>();
            double c = 200.2; double d = 300.3;
            Console.WriteLine(testClass2.AddWithDynamic(c, d));
         }


    }
    public class GenericOperation<T>
    {
        public GenericOperation()
        {
            var availableT = new Type[]
            {
            typeof(int), typeof(uint), typeof(short), typeof(ushort), typeof(long), typeof(ulong), typeof(byte),
            typeof(decimal), typeof(double)
            };
            if (!availableT.Contains(typeof(T)))
            {
                throw new NotSupportedException();
            }
            /*
            var p1 = Expression.Parameter(typeof(T));
            var p2 = Expression.Parameter(typeof(T));
            Add = Expression.Lambda<Func<T, T, T>>(Expression.Add(p1, p2), p1, p2).Compile();
            Subtract = Expression.Lambda<Func<T, T, T>>(Expression.Subtract(p1, p2), p1, p2).Compile();
            Multiply = Expression.Lambda<Func<T, T, T>>(Expression.Multiply(p1, p2), p1, p2).Compile();
            Divide = Expression.Lambda<Func<T, T, T>>(Expression.Divide(p1, p2), p1, p2).Compile();
            Modulo = Expression.Lambda<Func<T, T, T>>(Expression.Modulo(p1, p2), p1, p2).Compile();
            Equal = Expression.Lambda<Func<T, T, bool>>(Expression.Equal(p1, p2), p1, p2).Compile();
            GreaterThan = Expression.Lambda<Func<T, T, bool>>(Expression.GreaterThan(p1, p2), p1, p2).Compile();
            GreaterThanOrEqual = Expression.Lambda<Func<T, T, bool>>(Expression.GreaterThanOrEqual(p1, p2), p1, p2).Compile();
            LessThan = Expression.Lambda<Func<T, T, bool>>(Expression.LessThan(p1, p2), p1, p2).Compile();
            LessThanOrEqual = Expression.Lambda<Func<T, T, bool>>(Expression.LessThanOrEqual(p1, p2), p1, p2).Compile();
            */
        }

        public Func<T, T, T> Add { get; private set; }
        public Func<T, T, T> Subtract { get; private set; }
        public Func<T, T, T> Multiply { get; private set; }
        public Func<T, T, T> Divide { get; private set; }
        public Func<T, T, T> Modulo { get; private set; }
        public Func<T, T, bool> Equal { get; private set; }
        public Func<T, T, bool> GreaterThan { get; private set; }
        public Func<T, T, bool> GreaterThanOrEqual { get; private set; }
        public Func<T, T, bool> LessThan { get; private set; }
        public Func<T, T, bool> LessThanOrEqual { get; private set; }
    }
    class TestClass<T>
    {
        private GenericOperation<T> go = new GenericOperation<T>();
        public T AddWithDynamic(T a, T b)
        {
            return (dynamic)a + (dynamic)b;
        }


        public T AddWithExpressionTree(T a, T b)
        {
            return go.Add(a, b);
        }

    }
}

 何故か?ネットから拾ったコードではExpressionがエラーになったので、コメントアウトしたんですが、一応動きました。何故か?難しので説明はできません。

カテゴリー
C

独習C#第3版、ジェネリック型の初めての例

using System;

namespace Chapter01All
{
    class MyGeneric<T>
    {
        T num1;
        public MyGeneric(T obj1)
        {
            num1 = obj1;
        }
        public T GetNum1()
        {
            return num1;
        }
    }
    class GenericSampleDemo
    {
        static void Main()
        {
            MyGeneric<int> iOb;
            iOb = new MyGeneric<int>(100);
            int a = iOb.GetNum1();
            Console.WriteLine(a);
        }
    }
}

 本当は二つの数値を足すクラスを思い付きで、考えていました。そしたら意外に難しい内容を含んでいました。上の様にもう一個num2をメンバーに入れても、num1+num2はエラーになってしまいます。どうやら実行時点では、intだからいいように思っても、コンパイルが通りません。ネットを調べていたら、ちょうど探していた例がありますが、難しい。”(-“”-)”

カテゴリー
C

独習C#第3版、P469 delegateのサンプル

using System;

namespace Util
{
    delegate void EventHandler(String str);
    class SenderClass
    {
        public event EventHandler SomeEvent;
        public void Fire(String str)
        {
            if (SomeEvent != null)
                SomeEvent(str);
        }
    }
}

namespace Prog
{
    class Recieve
    {
        static void Handler(String str)
        {
            Console.WriteLine(str + "さん、今日は");
        }
        static void Main()
        {
            Util.SenderClass evt = new Util.SenderClass();
            evt.SomeEvent += Handler;
            evt.SomeEvent += delegate
            {
                Console.WriteLine("called");
            };
            evt.Fire("太郎");

        }
    }
}

 問題の意味を捉えることもできなかったのですが、前に出ていたサンプルをもとに、試行錯誤で書いてみました。今までの内容が詰まっていると思うので、悩んだときは再度見ても良いかと、サンプルになると思います。

カテゴリー
C

独習C#第3版、P462 名前空間の追加

using System;
namespace NMSSisokuenzan
{
    class SisokuEnzan
    {
        int firstNumber;
        int secondNumber;
        int wa;
        int sa;
        int seki;
        double waru;
        public SisokuEnzan(int x, int y)
        {
            firstNumber = x;
            secondNumber = y;
        }
        public void Kasan()
        {
            wa = firstNumber + secondNumber;
        }
        public void Genzan()
        {
            sa = firstNumber - secondNumber;
        }
        public void Kakezan()
        {
            seki = firstNumber * secondNumber;
        }
        public void Warizan()
        {
            waru = (double)firstNumber / secondNumber;
        }

        public int PKasan
        {
            get
            {
                return wa;
            }
        }
        public int PGenzan
        {
            get
            {
                return sa;
            }
        }
        public int PKakezan
        {
            get
            {
                return seki;
            }
        }

        public double PWarizan
        {
            get
            {
                return waru;
            }
        }

    }
}
using System;

namespace NMSSisokuenzan
{
    class NijyouClass
    {
        int x;
        int ans;
        public NijyouClass(int a)
        {
            x = a;
        }
        public void MakeAns()
        {
            ans = x * x;
        }
        public int Px
        {
            get
            {
                return ans;
            }
            set
            {
                x = value;
            }
        }
    }
}

上の数値を二乗するクラスを追加しました。namespaceはNMSSisokuenzanとして、元のものと同じくしてます。 上のプロパティでsetは使ってないので、削除してもOKでした。

using System;

namespace SisokuEnzanDemo
{
    using MyNS = NMSSisokuenzan.SisokuEnzan;
    using MyNSJ = NMSSisokuenzan.NijyouClass;
    class EnzanDemo
    {
         
        static void Main()
        {
            MyNS objMyNS = new MyNS(100, 200);
 
            objMyNS.Kasan(); objMyNS.Genzan(); objMyNS.Kakezan(); objMyNS.Warizan();
            Console.WriteLine(objMyNS.PKasan);
            Console.WriteLine(objMyNS.PGenzan);
            Console.WriteLine(objMyNS.PKakezan);
            Console.WriteLine(objMyNS.PWarizan);

            MyNSJ objMyNSJ = new MyNSJ(100);
            objMyNSJ.MakeAns();
            Console.WriteLine(objMyNSJ.Px);
        }
    }  
}
inserted by FC2 system