Visual Studio Code で C# コンソールアプリケーション実行とデバッグ

環境構築/実行

[1] .NET Core のサイトから .NET Core SDK を install
※自分は下記から .NET Core SDK 1.1 RC4 を選択 github.com

[2] コマンドラインでテンプレートを作成

dotnet new console
dotnet restore
dotnet run

f:id:danker512:20170713011106p:plain

[3] デバッグ実行(F5)

C#7 の Taple を使ってみる

  1. VSC の 拡張機能 で NugetPackageManager をインストール
  2. コマンドパレット(Ctrl+Shift+P)から NugetPackageManager -> System.ValueTuple -> 4.3.0 を選択

f:id:danker512:20170713011635p:plain

※「preLaunchTask build が見つかりませんでした」系の error が一度発生したが、VSC再起動で解決。

参考:
.NET Core のバージョンが難しい - しばやん雑記
Running C# 7 Code With Visual Studio Code Editor
【.NET Core 1.1】dotnet new コマンドで作成できるテンプレートのまとめ: Shion のブログ
Visual Studio Code でサクッと C# のコンソールアプリをデバッグしよう - Windows 編 - Xamarin 日本語情報

Tour of Heroes

The Hero Editor

app.components.ts

import { Component } from '@angular/core';

export class Hero {
  id: number;
  name: string;
}

@Component({
  selector: 'my-app',
  template: `
    <h1>Hello {{name}}</h1>
    <h2>{{hero.name}} details!!</h2>
    <div><label>id: </label>{{hero.id}}</div>
    
    <div>
      <label>name: </label>
      <input [(ngModel)]="hero.name" placeholder="name">
    </div>
  `
})

export class AppComponent {
  name = 'Tour of Heroes';
  hero: Hero = {
    id: 1,
    name: 'Windstorm'
  } 
}

app.modele.ts

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule }   from '@angular/forms'; <-

import { AppComponent }  from './app.component';

@NgModule({
  imports:      [ BrowserModule, FormsModule ], <-
  declarations: [ AppComponent ],
  bootstrap:    [ AppComponent ]
})

export class AppModule { }

Master/Detail

app.component.ts

import { Component } from '@angular/core';

const HEROES: Hero[] = [
  { id: 11, name: 'Mr. Nice' },
  { id: 12, name: 'Narco' },
  { id: 13, name: 'Bombasto' },
  { id: 14, name: 'Celeritas' },
  { id: 15, name: 'Magneta' },
  { id: 16, name: 'RubberMan' },
  { id: 17, name: 'Dynama' },
  { id: 18, name: 'Dr IQ' },
  { id: 19, name: 'Magma' },
  { id: 20, name: 'Tornado' }
];

export class Hero{
    id: number;
    name: string;
}

@Component({
    selector: 'my-app',
    template: `
        <h1>Tour of Heroes</h1>
        <h2>My Heroes</h2>
        <ul class="heroes">
            <li *ngFor="let hero of heroes" [class.selected]="hero === selectedHero" (click)="onSelect(hero)">
                <!-- each hero goes here -->
                <span class="badge">{{hero.id}}</span> {{hero.name}}
            </li>
        </ul>

        <div *ngIf="selectedHero">
          <h2>{{selectedHero.name}} details!</h2>
          <div><label>id: </label>{{selectedHero.id}}</div>
          <div>
            <label>name: </label>
            <input [(ngModel)]="selectedHero.name" placeholder="name"/>
          </div>
        </div>
    `,
    styles: [`
      .selected {
        background-color: #CFD8DC !important;
        color: white;
      }
      .heroes {
        margin: 0 0 2em 0;
        list-style-type: none;
        padding: 0;
        width: 15em;
      }
      .heroes li {
        cursor: pointer;
        position: relative;
        left: 0;
        background-color: #EEE;
        margin: .5em;
        padding: .3em 0;
        height: 1.6em;
        border-radius: 4px;
      }
      .heroes li.selected:hover {
        background-color: #BBD8DC !important;
        color: white;
      }
      .heroes li:hover {
        color: #607D8B;
        background-color: #DDD;
        left: .1em;
      }
      .heroes .text {
        position: relative;
        top: -3px;
      }
      .heroes .badge {
        display: inline-block;
        font-size: small;
        color: white;
        padding: 0.8em 0.7em 0 0.7em;
        background-color: #607D8B;
        line-height: 1em;
        position: relative;
        left: -1px;
        top: -4px;
        height: 1.8em;
        margin-right: .8em;
        border-radius: 4px 0 0 4px;
      }
    `]
})

export class AppComponent {
    title = 'Tour of Heroes';
    public heroes = HEROES;
    selectedHero: Hero;
    onSelect(hero: Hero): void { this.selectedHero = hero; }
}

Multiple Components

app.module.ts

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule }   from '@angular/forms';

import { AppComponent }  from './app.component';
import { HeroDetailComponent } from './hero-detail.component';

@NgModule({
  imports:      [ BrowserModule, FormsModule ],
  declarations: [ AppComponent, HeroDetailComponent ],
  bootstrap:    [ AppComponent ]
})

export class AppModule { }

app.components.ts

import { Component } from '@angular/core';
import {Hero} from './hero';


const HEROES: Hero[] = [
  { id: 11, name: 'Mr. Nice' },
  { id: 12, name: 'Narco' },
  { id: 13, name: 'Bombasto' },
  { id: 14, name: 'Celeritas' },
  { id: 15, name: 'Magneta' },
  { id: 16, name: 'RubberMan' },
  { id: 17, name: 'Dynama' },
  { id: 18, name: 'Dr IQ' },
  { id: 19, name: 'Magma' },
  { id: 20, name: 'Tornado' }
];

@Component({
    selector: 'my-app',
    template: `
        <h1>Tour of Heroes</h1>
        <h2>My Heroes</h2>
        <ul class="heroes">
            <li *ngFor="let hero of heroes" [class.selected]="hero === selectedHero" (click)="onSelect(hero)">
                <!-- each hero goes here -->
                <span class="badge">{{hero.id}}</span> {{hero.name}}
            </li>
        </ul>
        <hero-detail [hero]="selectedHero"></hero-detail>
    `,
    styles: [`
      .selected {
        background-color: #CFD8DC !important;
        color: white;
      }
      .heroes {
        margin: 0 0 2em 0;
        list-style-type: none;
        padding: 0;
        width: 15em;
      }
      .heroes li {
        cursor: pointer;
        position: relative;
        left: 0;
        background-color: #EEE;
        margin: .5em;
        padding: .3em 0;
        height: 1.6em;
        border-radius: 4px;
      }
      .heroes li.selected:hover {
        background-color: #BBD8DC !important;
        color: white;
      }
      .heroes li:hover {
        color: #607D8B;
        background-color: #DDD;
        left: .1em;
      }
      .heroes .text {
        position: relative;
        top: -3px;
      }
      .heroes .badge {
        display: inline-block;
        font-size: small;
        color: white;
        padding: 0.8em 0.7em 0 0.7em;
        background-color: #607D8B;
        line-height: 1em;
        position: relative;
        left: -1px;
        top: -4px;
        height: 1.8em;
        margin-right: .8em;
        border-radius: 4px 0 0 4px;
      }
    `]
})

export class AppComponent {
    title = 'Tour of Heroes';
    public heroes = HEROES;
    selectedHero: Hero;
    onSelect(hero: Hero): void { this.selectedHero = hero; }
}

hero-detail.component.ts

import { Component, Input } from '@angular/core';
import {Hero} from './hero';

@Component({
  selector: 'hero-detail',
  template: `
    <div *ngIf="hero">
      <h2>{{hero.name}} details!</h2>
      <div><label>id: </label>{{hero.id}}</div>
      <div>
        <label>name: </label>
        <input [(ngModel)]="hero.name" placeholder="name"/>
      </div>
    </div>
  `
})

export class HeroDetailComponent {
    @Input() hero: Hero;
}

hero.ts

export class Hero {
  id: number;
  name: string;
}

Services

hero.service.ts

import { Injectable } from '@angular/core';

import { Hero } from './hero';
import { HEROES } from './mock-heroes';

@Injectable()

export class HeroService {
  getHeroes(): Promise<Hero[]> {
    return Promise.resolve(HEROES);
  }
}

app.component.ts

import { Component, OnInit } from '@angular/core';
import { Hero } from './hero';
import { HeroService } from './hero.service';

@Component({
    selector: 'my-app',
    template: `
        <h1>Tour of Heroes</h1>
        <h2>My Heroes</h2>
        <ul class="heroes">
            <li *ngFor="let hero of heroes" [class.selected]="hero === selectedHero" (click)="onSelect(hero)">
                <!-- each hero goes here -->
                <span class="badge">{{hero.id}}</span> {{hero.name}}
            </li>
        </ul>
        <hero-detail [hero]="selectedHero"></hero-detail>
    `,
    styles: [`
      .selected {
        background-color: #CFD8DC !important;
        color: white;
      }
      .heroes {
        margin: 0 0 2em 0;
        list-style-type: none;
        padding: 0;
        width: 15em;
      }
      .heroes li {
        cursor: pointer;
        position: relative;
        left: 0;
        background-color: #EEE;
        margin: .5em;
        padding: .3em 0;
        height: 1.6em;
        border-radius: 4px;
      }
      .heroes li.selected:hover {
        background-color: #BBD8DC !important;
        color: white;
      }
      .heroes li:hover {
        color: #607D8B;
        background-color: #DDD;
        left: .1em;
      }
      .heroes .text {
        position: relative;
        top: -3px;
      }
      .heroes .badge {
        display: inline-block;
        font-size: small;
        color: white;
        padding: 0.8em 0.7em 0 0.7em;
        background-color: #607D8B;
        line-height: 1em;
        position: relative;
        left: -1px;
        top: -4px;
        height: 1.8em;
        margin-right: .8em;
        border-radius: 4px 0 0 4px;
      }
    `],
    providers: [HeroService]
})

export class AppComponent implements OnInit {
  title = 'Tour of Heroes';
  heroes: Hero[];
  selectedHero: Hero;
 
  constructor (private heroService: HeroService) { }
 
  getHeroes(): void {
    this.heroService.getHeroes().then(heroes => this.heroes = heroes);
  }
 
  ngOnInit(): void {
    this.getHeroes();
  }
 
  onSelect(hero: Hero): void {
    this.selectedHero = hero;
  }
}

mock-heroes.ts

import { Hero } from './hero';
 
export const HEROES: Hero[] = [
  { id: 11, name: 'Mr. Nice' },
  { id: 12, name: 'Narco' },
  { id: 13, name: 'Bombasto' },
  { id: 14, name: 'Celeritas' },
  { id: 15, name: 'Magneta' },
  { id: 16, name: 'RubberMan' },
  { id: 17, name: 'Dynama' },
  { id: 18, name: 'Dr IQ' },
  { id: 19, name: 'Magma' },
  { id: 20, name: 'Tornado' }
];

Routing

Routing に関しては、理解するのに時間が掛かった。
重要だと思う部分を列挙してみる。
server-side rendering で言うと、Controller に近いのかな。 コード内の不明な箇所は F12 (VisualStudioCode) で定義に移動して行くと繋がりが見えてくる気がする!

  • Routing is another name for navigation. The router is the mechanism for navigating from view to view.
    Routing はナビゲーションの別の名前。Router は View と View を繋ぐメカニズム。
  • RouterModuleは、外部オプションなので package のような形で読み込む
  • Routing 専用のクラスは RoutingModule へ

Router outlet

Route は Path を HeroRoute に一致させ、HeroesComponentを表示させる。 ただし、Router にコンポーネントの表示先を伝える必要があるため、テンプレートの最後に <router-outlet> 要素を追加する。 RouterOutlet は、RouterModule によって提供されるディレクティブの1つである。

app.module.ts

import { NgModule }       from '@angular/core';
import { BrowserModule }  from '@angular/platform-browser';
import { FormsModule }    from '@angular/forms';

import { AppComponent }         from './app.component';
import { DashboardComponent }   from './dashboard.component';
import { HeroDetailComponent }  from './hero-detail.component';
import { HeroesComponent }      from './heroes.component';
import { HeroService }          from './hero.service';

import { AppRoutingModule }     from './app-routing.module';

@NgModule({
  imports: [
    BrowserModule,
    FormsModule,
    AppRoutingModule
  ],
  declarations: [
    AppComponent,
    DashboardComponent,
    HeroDetailComponent,
    HeroesComponent
  ],
  providers: [ HeroService ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }

app-routing.module.ts

import { NgModule }             from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

import { DashboardComponent }   from './dashboard.component';
import { HeroesComponent }      from './heroes.component';
import { HeroDetailComponent }  from './hero-detail.component';

const routes: Routes = [
  { path: '', redirectTo: '/dashboard', pathMatch: 'full' },
  { path: 'dashboard',  component: DashboardComponent },
  { path: 'detail/:id', component: HeroDetailComponent },
  { path: 'heroes',     component: HeroesComponent }
];

@NgModule({
  imports: [ RouterModule.forRoot(routes) ],
  exports: [ RouterModule ]
})
export class AppRoutingModule {}

app.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `
    <h1>{{title}}</h1>
    <nav>
      <a routerLink="/dashboard" routerLinkActive="active">Dashboard</a>
      <a routerLink="/heroes" routerLinkActive="active">Heroes</a>
    </nav>
    <router-outlet></router-outlet>
  `,
  styleUrls: ['./app.component.css'],
})

export class AppComponent {
  title = 'Tour of Heroes';
}

heroes.component.ts

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';

import { Hero } from './hero';
import { HeroService } from './hero.service';

@Component({
  selector: 'my-heroes',
  templateUrl: './heroes.component.html',
  styleUrls: [ './heroes.component.css' ]
})

export class HeroesComponent implements OnInit {
  heroes: Hero[];
  selectedHero: Hero;

  constructor(
    private router: Router,
    private heroService: HeroService) { }

  getHeroes(): void {
    this.heroService.getHeroes().then(heroes => this.heroes = heroes);
  }

  ngOnInit(): void {
    this.getHeroes();
  }

  onSelect(hero: Hero): void {
    this.selectedHero = hero;
  }

  gotoDetail(): void {
    this.router.navigate(['/detail', this.selectedHero.id]);
  }
}

hero.service.ts

import { Hero } from './hero';
import { HEROES } from './mock-heroes';
import { Injectable } from '@angular/core';

@Injectable()
export class HeroService {
  getHeroes(): Promise<Hero[]> {
    return Promise.resolve(HEROES);
  }

  getHeroesSlowly(): Promise<Hero[]> {
    return new Promise(resolve => {
      // Simulate server latency with 2 second delay
      setTimeout(() => resolve(this.getHeroes()), 2000);
    });
  }

  getHero(id: number): Promise<Hero> {
    return this.getHeroes()
               .then(heroes => heroes.find(hero => hero.id === id));
  }
}

参考:https://angular.io/tutorial/

async/await

async/awaitについて、理解するために書いてみた。

まだまだ、関連するメソッドや細かい仕様部分は調べつつ扱っていかなければ...
「非同期処理って何だろう?」の事始めにして、感覚を掴む記事になれば幸い

Point

  • async/awaitC# 5.0から導入されたTaskと紐づく構文
  • Taskは単なる手順書!
    asyncは単なる非同期メソッド!awaitはタスクの完了を待ち、取り出す!

これを抑えておけば、あとは下記のコードを見てもらえるとすぐ分かると思う。

f:id:danker512:20170604184732p:plain

asyncTask.Wait(); の部分とかコメントアウトするともっと体感できると思う
※メイン処理が早く終わってしまうので、待ち時間は10秒に変更

f:id:danker512:20170604190213p:plain

参考:
C# Task async, await の使い方 - mcommit's message
Taskを極めろ!async/await完全攻略 - Qiita

NOT EXISTSで差分抽出

サブクエリーが少なくとも1行を返す場合、EXISTS subquery は TRUE、NOT EXISTS subquery は FALSE。 下記の例は、aとbのテーブルの列名Aと列名Bを比較し一致しないものを返す。

例:

select * from テーブル名A as a
where not exists (
    select * from テーブル名B as b
    where a.列名A = b.列名B  // 条件
)
and a.列名A' = xxx

開発DBに不正な値があり、それがどの子か特定した経緯。

EnumのTryParse

第1引数には変換する文字列を指定する。 第2引数には変換された値を受け取る型の変数を指定する。

Enum.Parse とは異なり、例外をスローすることなく、変換できる。

Foo foo;
if (!Enum.TryParse(bar.ToString(), out foo))
{
    throw new InvalidCastException($"Fooには定義されていない値が選択されてます");
}

参考:Enum.TryParse(TEnum) メソッド (String, TEnum) (System)

値型と参照型

値型/参照型、構造体/クラス備忘録

値型はオブジェクト内にインライン定義され、 参照型は、実データをヒープに格納する。

その型をどのように扱うかを考え、 多様性(ポリモーフィズム)を持つか否かを考える必要がある。

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace UnitTestProject1
{
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestMethod1()
        {
            // 値型
            var valueType = new ValueType
            {
                value = 1
            };
            
            // 参照型
            var classType = new ClassType
            {
                value = 1
            };

            Plus(valueType, classType);

            Assert.AreEqual(1, valueType.value);
            Assert.AreEqual(2, classType.value);
        }

        static void Plus(ValueType valueType, ClassType classType)
        {
            valueType.value += 1;
            classType.value += 1;
        }

        struct ValueType { public int value; }
        class ClassType { public int value; }
    }
}