【C#】valueがlistのDictionary


 var mData = new Dictionary<string, List<string>>
 {
  { "X", new List<string>() { "あ", "い", "う" } },
  { "Y", new List<string>() { "か", "き", "く" } },
  { "Z", new List<string>() { "さ", "し", "す" } }
 };
 
 var sData = new Dictionary<string, List<string>>
 {
  { "X", new List<string>(){ "あ", "あ", "あ", "い", "う", "う" } },
  { "i", new List<string>(){ "subI1", "subI2", "subI3", "subI1", "subI1", "subI2" } },
  { "j", new List<string>(){ "subJ1", "subJ2", "subJ3", "subJ1", "subJ1", "subJ2" } }
 };
 
 var key = "X";
 
 var mDataValueSize = mData.Max(kv => kv.Value.Count); // valueのlistの要素数は全て同一と仮定
 var mSeq = Enumerable.Range(0, mainDataValueSize); // 第一引数は開始位置, 第二引数は個数で連続する配列
 foreach (var m in mSeq) {
  var keyValue = mData[key].ElementAt(m);
  var sIndex = sData[key].IndexOf(keyValue);
  var seq = sData[key].Where(kv => kv == linkingKeyValue).Count();
  var subSeq = Enumerable.Range(sIndex, seq);
  foreach (var s in subSeq) {
   var oneRec = sData.ToDictionary(kv => kv.Key, kv => kv.Value.ElementAt(s));
  }
 }

【C#】継承

文法


class 派生クラス名 : 基底クラス{}

継承とは

あるクラスを元(基底)として新しいクラス(派生)を作成すること
派生クラスのインスタンスは暗黙的に基底クラスのインスタンスを持つ
このため、基底クラスのメンバにもアクセスすることができる

隠蔽

派生クラス側で、基底クラスのpublicメンバと同名のメンバを再定義すること。
メンバの実体が1つに収束するわけではなく、基底クラスと派生クラスのメンバが重複している。
例)基底クラス

class MyBase
{
    public void Exec() => System.Console.WriteLine("This is Base.");
}
例)派生クラス

class MyInheritance : MyBase
{
    public void Exec() => System.Console.WriteLine("This is Inheritance.");
}
メンバの隠蔽では、基底クラスと派生クラスのメンバが重複しているため、どちらが使われるかは、型によって決定される。

class Program
{
    static void Main()
    {
        MyBase mb = new MyInheritance();
        mb.Exec(); // This is Base.
        MyInheritance mh = new MyInheritance();
        mh.Exec(); // This is Inheritance.
        auto mh2 = new MyInheritance();
        mh2.Exec(); // This is Inheritance.
    }
}

明示的な隠蔽

意図しない隠蔽である場合もあるため、上記の例の場合にコンパイラは警告を発してくれる。
コンパイラ(他の開発者にも)に意図した隠蔽であることを伝えるためには「new 修飾子」を用いる。

class MyInheritance : MyBase
{
    public new void Exec() => System.Console.WriteLine("This is Inheritance");
}

継承の禁止

現在のクラスを継承されたくない場合は「sealed 修飾子」を用いる。

sealed class MyBase
{
    public void Exec() => System.Console.WriteLine("This is Base.");
}
これで、以下のコードはエラーになる。

class MyInheritance : MyBase{}

多重継承の禁止

派生クラスは暗黙的に基底クラスのインスタンスを持っているため、C#では多重継承を禁止している。

【文字コード】入門

文字コード(Character Code)

 文字や記号をコンピュータ上でデータとして扱うために、1文字ずつ固有のビット列(0と1)を与えた符号のこと
 通常、7ビット(128通り)または8ビット(256通り)を最小単位とする。

文字集合

文字コードを定義するためには、言語と対象の文字に対して列挙した文字集合を定める必要がある。
このとき、
  • 文字群:レパートリ
  • 一意の番号を与えたもの:符号化文字集合
と言い、各文字に与えられた番号を「符号位置(code point)」と言う。
代表的な符号化文字集合はJIS X 0201、JIS X 0208、Unicodeなど

Unicode

当初は16ビット(65536通り)であったが、21ビット弱(1114112:U+0000~U+10FFFFF)まで拡張された。
符号位置は4桁以上の16進数(例」U+20B9F)で、6桁の16進数で表したとき、最初の2桁を「面(00面~ff面)」、次の2桁を「区(00区~ff区)」、最後の2桁を「点(00点~ff点)」と呼ぶ
基本は「1文字=2バイト」だが、1部の文字は「1文字=4バイト」(サロゲートペア)
従来のUnicodeでは未使用だった0xD800~0xDBEF(1024通り)を上位サロゲート、0xDC00~0xDFFF(1024通り)を下位サロゲートとして、「上位サロゲート+下位サロゲート」の4バイトで文字を表現
例)ǹ
ベースとなる「n」の直後に合成用の「'」と付ける

符号化方式

文字数が少ない欧米圏では8ビット文字のように符号化文字集合をそのまま文字コードとする場合もあるが、 日本語等の文字数が多い場合は、符号をどのようにビット列で表現するかを定めている場合があり、これが文字エンコーディング(符号化方式)である。
JIS, Shift JIS, UTF-8, UTF-16, UTF-32

UTF-16

16bitの符号なし整数値によってUnicodeのコードポイントを表現するエンコード方式

UTF-32

32bitの符号なし整数値によってUnicodeのコードポイントを表現するエンコード方式
Unicodeの有効ビット数は21ビット弱なので、変換は不要で上位ビットを0埋めすれば良い
バイト列の変換については、ビッグエンディアンがデフォルトで、データの先頭にエンディアンを指定する「バイト順マーク」がつくことがある。
  • ビッグエンディアン:00 00 FE FF
  • スモールエンディアン:FF FE 00 00

UTF-8

最も後発の文字エンコードで、8bitを1単位として、1~4単位までの連続した単位列によって、Unicodeの1コードポイントを表現
1単位だけで、コードポイントを表現するときは、下位7bitはASCIIと等しく、ASCIIを使っていたコードやシステムと親和性が高く、最も普及しているエンコード

【Java】画像ファイルを2分割する

分割側コード


import java.awt.image.BufferedImage;
import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import javax.imageio.ImageIO;

public class ImageDivided {
  private InputStream inputStream;
  
  public ImageDivided(InputStream inputStream) {
    this.inputStream = inputStream;
  }
  
  public ArrayList<BufferedImage> GetDividedInto2(){
    var ret = new ArrayList<BufferedImage>(2);
    try{
      var originalImage = ImageIO.read(this.inputStream);

      var width = originalImage.getWidth();
      var height = originalImage.getHeight();
      var halfWidth = width / 2;

      var leftHalfImage = originalImage.getSubimage(0, 0, halfWidth, height);
      var rightHalfImage = originalImage.getSubimage(halfWidth, 0, halfWidth, height);
      ret.add(leftHalfImage);
      ret.add(rightHalfImage);
    }catch(Exception e){
    }
    return ret;
  }
}

使う側コード


import java.io.File;
import java.io.FileInputStream;

import javax.imageio.ImageIO;
import javax.imageio.ImageWriter;

public static void main(String[] args){
  var imageDivided = new ImageDivided(new FileInputStream(画像ファイル));
  
  var ret = imageDivided.GetDividedInto2();
  
  var writers = ImageIO.getImageWritersByFormatName("jpeg");
  var writer = (ImageWriter)writers.next();
  
  var outputStream = ImageIO.createImageOutputStream(new File(出力ファイル1));
  writer.setOutput(outputStream);
  writer.write(ret.get(0));
  
  outputStream = ImageIO.createImageOutputStream(new File(出力ファイル2));
  writer.setOutput(outputStream);
  writer.write(ret.get(1));
}

【C#】Disposeパターン

using

usingは自動的に、finallyで必ずDispose()を呼び出すtry...finallyを作成するだけ。
ただし、メンバ等にはusingが使えない。。。⇒Disposeパターン

Dispose()の必須事項

  1. 安全に複数回呼び出し可能であること
  2. インスタンスが保持しているリソース(OSや外部DLLが管理するもの)を解放すること
  3. 必要ならば、基本クラスのDispose()を呼ぶこと
  4. このクラスのファイナライザを抑制して、GCがファイナライズキュー上のオブジェクト数を減らすための手助けをする
  5. 基本的に例外をスローしない

Disposeパターン

マネージドリソースとアンマネージドリソースを解放
ベースクラス
IDisposeを継承し、Dispose()、Dispose(bool disposing)、ファイナライザを実装
解放処理はDispose(bool disposing)で行い、Dispose()とファイナライザをそれを呼び出す
サブクラス
Dispose(bool disposing)のみをオーバーライド


public class Base : System.IDisposable
{
  private bool isDisposed; // Disposeされたかを表すフラグ
  
  public Dispose()
  {
    this.Dispose(true); // 解放処理はDispose(bool disposing)で行い、Dispose()とファイナライザをそれを呼び出す
    System.GC.SuppressFinalize(this); // 二重解放を避ける
  }
  
  ~Base()
  {
    this.Dispose(false); // 解放処理はDispose(bool disposing)で行い、Dispose()とファイナライザをそれを呼び出す
  }
  
  
  protected virtual void Dispose(bool dispose)
  {
    if (this.isDisposed) return; // 安全に複数回呼び出し可能
    if (dispose)
    {
      // マネージリソースの解放(ex:ストリーム)
    }
    
    // アンマネージリソースの解放
    
    this.isDisposed = true; // 安全に複数回呼び出し可能
  }
}
Visual Studioならば、1行目の時点で、「破棄パターンを使ってインターフェイスを実装します」ある程度作成してくれる。

【C#】環境系

環境変数の値を取得


var ret = System.Environment.GetEnvironmentVariable("環境変数名");
// 変数名があれば値、なければNULL

実行中のプログラムのexe/dllのパスを取得


var ret = System.Reflection.Assembly.GetExecutingAssembly(); // 実行中のアセンブリ
var path = System.IO.Path.GetDirectoryname(new System.Uri(ret.Location).LocalPath); // exe,dllのディレクトリ

【C#】ファイル系

存在チェック


System.IO.File.Exists("パス"); // Trueならファイルが存在
System.IO.Directory.Exists("パス"); // Trueならディレクトリが存在

パスがローカルか


var uri = new System.Uri("パス");
uri.IsLoopback; // Trueならローカル

ループバック

送ったものが、そのまま自分に戻ってくること。 ネットワークの世界では、自分を表すIPアドレスである、ループバックアドレスというものが用意されている。