C#_二次元 List と List の配列

List<int>             listA = new List<int>();
List<int[ ]         listB = new List<int[ ]>();
List<List<int>>  listC = new List<List<int>>();

List<int>[ ]          listZ = new List<int>[n];

の違いについて。

 

箱は List 型
List<int>             → 中に入っている小箱は int 型
List<int[ ]>         → 中に入っている小箱は int 型の配列
List<List<int>> → 中に入っている小箱は int 型の List

箱は 配列型
List<int>[ ]         → 中に入っている小箱は int 型の List

 

List<int>

f:id:koshinRan:20170615011201j:plain

サイズ( Listの長さ )は決まっていない

    listA.Add(10);
    listA.Add(11);
    listA.Add(12);

 

List<int[ ]>

f:id:koshinRan:20170615012254j:plain

listB のサイズ決まっていない
だが、listB の要素の中身 int[ ] なので、サイズは決まっている

    //各要素の int[ ] は異なる長さでもOK
    listB.Add(new int[4] { 40, 41, 42, 43 });
    listB.Add(new int[3] { 30, 31, 32 });
    listB.Add(new int[2] { 20, 21});

 

List<List<int>>

f:id:koshinRan:20170615012354j:plain

listCサイズ決まっていない
listC の要素の中身も List なので、サイズは決まっていない

    listC.Add(new List<int>());
    listC[0].Add(10);
    listC[0].Add(11);

    List<int> e = new List<int>();
    e.Add(99);
    e.Add(88);
    e.Add(77);
    e.Add(66);
    listC.Add(e);
   
    //listC[0] => 10, 11
    //listC[1] => 99, 88, 77, 66

 

List<int>[ ]

listZ配列なのでサイズは決まっている
だが、listZ の要素の中身は List なので、サイズは決まっていない

f:id:koshinRan:20170615013037j:plain

    //List<int>[] listZ = new List<int>[4];
    //↑ は、( List型で要素を 4 つ持つ )配列のインスタンス作成。

    //List のインスタンスは作成されていない。する必要がある。
    listZ[0] = new List<int>();
    listZ[1] = new List<int>();
    listZ[2] = new List<int>();
    listZ[3] = new List<int>();

    listZ[0].Add(100);
    listZ[0].Add(101);
    listZ[0].Add(102);

    listZ[1] = e;
    listZ[2] = listA;

    List<int> l = new List<int>();
    l.Add(300);
    l.Add(301);
    listZ[3] = l;
   
    //listZ[0] => 100, 101, 102
    //listZ[1] => 99, 88, 77, 66
    //listZ[2] => 10, 11, 12
    //listZ[3] => 300, 301

 

以上。

ベクトルと位置との対応付け

前回、いくつかの数値をまとめて表す時の記法を書いた。

 

今回は、
2~3つの数値がまとまっている場合は、空間での位置を表すことができる
という内容。

 

空間での位置

2 次元ベクトル・3 次元ベクトルは、方眼紙上にプロットできる。
(3, 14)T なら、x軸:3、 y軸:14
(5, -1)T なら、x軸:5、y軸:-1
(4, 3, 2)T なら、x軸:4、y軸:3、z軸:2
ゼロベクトル o = (0, 0)T は原点O。

ex) (5, -1)

f:id:koshinRan:20170613015359j:plain

 ただの数値の塊を、空間での位置に対応付けることを強調する時は、
位置ベクトル」と呼ぶ。

 

矢印

「位置」という解約の他に、
原点 O からその位置に向かう「矢印」という解釈もある。

矢印解釈だと
足し算は、矢印の継ぎ足し定数倍は、長さの伸縮
( a + b = b + a は、a 進んでから b 進んでも、
b 進んでから a 進んでも行き先は同じということ )

f:id:koshinRan:20170613233232j:plain        f:id:koshinRan:20170613234112j:plain

 

一次ベクトル

一次元ベクトル (a) と数 a どちらも、直線上の 1 点として表せる。
だが、単位の取り方によって値が変わってしまうので、注意。
( 基底にからんだ問題 )
プログラミング言語でも、サイズ 1 の配列と数値は別物。

 

以上。

C#_自動でスクロールバーを一番下に持ってくる

動的にpanel の中にコントロ ールが増えていき、
スクロールする領域が増えた時、自動で一番下にバーの位置を設定。

ソース

//スクロールをpanel1の底へ
panel1.AutoScrollPosition
= new Point(panel1.AutoScrollPosition.X, panel1.Height + panel1.VerticalScroll.Value);

※水平スクロールバーはない。
※ AutoScroll は True。
※ VerticalScroll.Value は( 垂直バーの )現在位置を表す。

 

AutoScrollPosition

スクロールさせる位置を設定する。
または
位置を取得する。

設定
スクロールの開始位置からどれだけ離れるかを、
正の整数で設定する。
水平スクロールバーでは右、垂直スクロールバーでは下に
移動させるほど大きな値となる。

取得
スクロールの開始位置からどれだけ離れているかを、
負の整数で取得できる。

ex )
AutoScrollPointで (100, 200)という位置を設定した後、
AutoScrollPointを取得すると(-100, -200)となる。

 

↓ のようなメソッドもある。

ScrollControlIntoView

引数に指定したコントロ ールまでスクロールする。

親コントロ ール.ScrollControlIntoView( 子コントロ ール )

ex)

panel1.ScrollControlIntoView(buttonA);
//panel1 の上に乗っている buttonA が見えるまで、
//スクロールする。

 

こちらから。
http://blogs.wankuma.com/mrt/archive/2008/05/27/139640.aspx
https://dobon.net/vb/dotnet/form/autoscrollposition.html

 

以上。

ソース見返して、これ必要?と思うコードあるが
現状想定通りに動いているのでこのままにしておく。

 

C#_スクロールバーの連動

Panel 1 ~ 4 のどれか一つの Panel のスクロールバーを動かしたら、
他のスクロールバーも連動して動くようにする。

f:id:koshinRan:20170611194121j:plain

Panel 1 ~ 4 のプロパティにあるイベントのアクション「Scroll」で
スクロールされたら呼ばれるメソッド名を入力。
下では panel_Scroll としている。

f:id:koshinRan:20170611191530j:plain

 

ソース

        private void panel_Scroll(object sender, ScrollEventArgs e)
        {
            Panel getPanelScroll = (Panel)sender;

            int x = getPanelScroll.HorizontalScroll.Value;
            int y = getPanelScroll.VerticalScroll.Value;

            panel1.AutoScrollPosition = new Point(x, y);
            panel2.AutoScrollPosition = new Point(x, y);
            panel3.AutoScrollPosition = new Point(x, y);
            panel4.AutoScrollPosition = new Point(x, y);
        }

尚、同じメソッドを呼び出したかったため、下記のソースでは実現できなかった。
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1363602278

 

object 型の sender 引数

発生元のオブジェクトが入っている。
(ボタンをクリックしたなら、ボタンの情報)
中身を見ると、
Anchor や AutoScroll、Dock や Location などなど。

ex) では、発生元オブジェクトは Panel なので、
Panel に変換して、各情報を取得する必要がある。
sender.HorizontalScroll.Value;
の場合は、「HorizontalScroll の定義が含まれてないよ」
と怒られる。

 

ScrollEventArgs 型の e 引数

イベント情報が入っている。
スクロールバーを動かす前の位置や、動かした現在の位置などが格納。

イベントごとによって型が異なる。

 

 こちらから参照。

https://msdn.microsoft.com/ja-jp/library/system.windows.forms.scrollablecontrol.autoscrollposition(v=vs.110).aspx
https://dobon.net/vb/dotnet/form/autoscrollposition.html
http://blogs.wankuma.com/mrt/archive/2008/05/27/139640.aspx
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1357258528

 

以上。

 


 

C#_abstract とは

 ・abstract キーワードで宣言する。

・abstract 宣言されたならば、派生クラスで必ず実装

・派生クラスにて足りない機能を実装した上で、インスタンス
  生成しなくてはならない。

 

抽象クラス

インスタンス化できないクラス
他のクラス ( 派生クラス ) のベースとなるだけという宿命のもとに
誕生したクラス。

 

抽象メソッド

メソッドの意味 ( 規約 ) だけを定義したメソッド。
派生クラスで具体的な実装を行う。抽象クラスの中に記述する。

 

ex ) コード
基底クラス

    abstract class Base
    {
        public abstract void Request();
    }

 

派生クラス

    class Sub : Base
    {
        public override void Request()
        {
            // 処理
        }
    }

 

呼び出し元

    public class Main
    {
        Sub sub = new Sub();
        sub.Request();

        //↓NG.
        //Base bas = new Base();
    }

 

abstract は何を解決しているのか

Base クラスで意味のない値を返さず、派生クラスで実装する場合。

1 )

Base を継承せずにインスタンスを生成すると
(Base のインスタンスを作成すると)、
意味のない値を返すメソッドを持つクラスのインスタンスが生成されてしまい、
好ましくない。

2 )

1 ) の解決策として、外部から Base クラスのインスタンス
生成できないようにする為、
Base クラスのコンストラクタを protected にする。

だが、Sub クラスでしっかりとオーバーライドしなければ
無意味な値が返されてしまう。

これを解決する為、
インスタンスを生成できないクラス、
派生クラスで必ずオーバーライドしなければならないメソッドの定義
する為に構文 abstract がある。

 

オーバーライド:
基底クラスで定義したメソッドを、その派生クラスで再定義すること。

 

+α
何故インスタンス化できないのか

現実世界では、「犬」というインスタンスはない。
犬をベースとして柴犬、秋田犬などの種類、これらのインスタンスを見ている。
犬を見ているのではなく、犬を継承した各種類の犬を見ている。

プログラムは実世界を落とし込んでいるので、
「犬」であるBase のインスタンスが生成されたらおかしいよね、
ということだと思う。

 

こちら参照。

http://ufcpp.net/study/csharp/oo_abstract.html
http://www.kisoplus.com/kihon/tyu.html

 

 以上。

C#_拡張メソッド

静的メソッドをインスタンスメソッドと同じ形式で
呼び出せるようにしたもの

特徴

  1. 前置き記法である静的メソッドを後置き記法でかける
  2. あたかも新しいクラスにメソッドを追加したかのように見せる
  3. 定義側第 1 引数の前に this を付ける
  4. 利用側:インスタンスメソッドと同じ書き方。

(関数指向。オブジェクト指向ではない)

 

コード

Ⅰ) int x = int.Parse("1");

Ⅱ) int x = "1".Parse();

と書けるようになる。

hoge = new Hoge();
hoge.hhhh();            ←インスタンスメソッド

 

Ⅱ) を書くためには、

static class Extensions
{
    public static int Parse(this string str)
    {
        return int.Parse(str);
    }
}

という静的メソッドを用意する。

 

2 ) の 新しいクラスにメソッドを追加したかのように~。について

→既存のクラスにメソッドを追加している(ようにみえる)ので
拡張メソッドという。
(以前はクラスの機能拡張=メソッド追加をしたければ、
継承などして新しいクラスを作る必要があった。)

定義方法

静的クラス(static class)の中、第一引数に、
this を修飾子としてつけた static メソッドを書く。

ex)

static class StringExtensions
{
    public static string ToggleCase(this string s)
    {
        //処理
    }
}

以下のように呼べる。

string s = "This is a Test."
//通常の呼び出し方
string s1 = StringExtensions.ToggleCase(s);
//拡張メソッドの呼び出し
s.ToggleCase();

 


---using ディレクティブによる拡張メソッドのインポート---

通常、静的メソッドは「クラス名.メソッド名」という記法で呼ぶ。
だが、拡張メソッドは「クラス名」をさぼって書けるようになっている。

では「どのメソッドが呼ばれるか」を決定しているのか。

「using ディレクティブ」で指定した名前空間の中にある拡張メソッド
参照されるようになっている
故に、
同じ名前空間内に2つ以上同名の拡張メソッドを定義してはいけない

 

他、優先順位やら問題点、意義があるが深そうなので後回し。
とりあえず、インスタンスが必要でないメソッド静的で
と言われているので、静的でかく。

 

こちらから。
http://ufcpp.net/study/csharp/sp3_extension.html

 

以上。

C#_Panel 設置の順と Dock 設定

※ デザインからの設定。

f:id:koshinRan:20170608214455j:plain

Panel を設置する時

Panel は設置した順に Dock プロパティに準じて
    親コントロ ール領域を埋めていっている

・設置できるのは未使用領域の箇所。

とイメージしながら行っている。

 

ex )
以下のような Panel 配置にしたい時、
どのような順で Panel を設置して、
どのような Dock プロパティを設定すればよいか。

f:id:koshinRan:20170608214544j:plain

結論から

・ Panel の設置順

Panel → Panel → Panel

 

・ Dock の設定

Panel Bottom
Panel Left
Panel Fill

( Panel を設置したらDock を設定 → Panelを設置したら… の方が良いかと)

f:id:koshinRan:20170608215136j:plain

 

説明もどき

最前面に来てほしい Panel を最初に設置する。
例 の場合は、の Panel。

の Panel と の Panel どちらを先に設置するかだが、
の Panel先に設置する。

 

これを先に、 Panel を設置し、 Panel を設置した後に Dock を行うと、
Panel が Panel の下に来てしまう。

f:id:koshinRan:20170608215254j:plain
分かりづらいが、 Panel の A B J K
Panel の A B J K に隠れてしまっている。

 

これは PC 側が、Panelを 設置した順に Dock を行うため ( だったと思う )。
Panel を 2 番目に設置しているので、Dock:Fill が 2 番目に行われる。
Panel が置かれている以外の領域を Fill (埋める) なので、
以下のようになる。

f:id:koshinRan:20170608215357j:plain

3 番目に Panel を設置して、Left にしても、
既に Panel が埋めているので、 Panel の上に 据えるしかない。


以上。