今日のC#インタラクティブ (2017/06/18) ~単位変換編~

こんにちは、Takymです。
今日もはりっきてC#インタラクティブを実行しましょう!


VS2017起動するの面倒くさいからcsi.exeを使おう
http://almostcorrect.blog.fc2.com/blog-entry-3.htmlに載っている摂氏・華氏の公式を実行してみる。

> (9 / 5) * 1 + 32 // 1℃を華氏に変換
33
> (9 / 5) * 2 + 32 // 2℃を華氏に変換
34
> (9 / 5) * 3 + 32 // 3℃を華氏に変換
35
// ↑あれ?なんかおかしい。
// あ、そうか!intで計算していたw
// ちゃんとfloatとかdoubleで計算しないと・・・
> (9F / 5F) * 3F + 32F // 3℃を華氏に変換
// これで、どうだ?
37.4
// おお、成功。
> (9F / 5F) * 2F + 32F // 2℃を華氏に変換
35.6
> (9F / 5F) * 1F + 32F // 1℃を華氏に変換
33.8
// そういえば、5分の9ってどのくらい?
> 9F / 5F
1.8
> 1.8 * 5
9
// 1.8か。

今度は何を計算しよう?
センチメートルとフィートを変換しよう。
https://www.google.com/search?q=cm+ft+%E5%A4%89%E6%8F%9B

> 1 * 0.0328084 // 1cmを変換する。
0.0328084
// 一倍だからね。
> 2 * 0.0328084 // 2cmを変換する。
0.0656168
> 3 * 0.0328084 // 3cmを変換する。
0.0984252

次は何を計算しようかな?
1lb=453.592g
https://www.google.com/search?q=%E3%82%B0%E3%83%A9%E3%83%A0+%E3%83%91%E3%82%A6%E3%83%B3%E3%83%89

> 2 * 453.592 // 2lbを変換する。
907.184
> 3 * 453.592 // 3lbを変換する。
1360.7759999999998
> 4 * 453.592 // 4lbを変換する。
1814.368

飽きた。今回はもうやめよう。

今日のC#インタラクティブ (2017/06/17) ~循環継承編~

こんにちは、Takymです。
今日もC#インタラクティブを頑張っていきます。

> public class A_0000 : A_0000 { }
(1,14): error CS0146: 'A_0000' と 'A_0000' を含む、循環する基底クラスの依存関係です。
// まぁ、そうなるよね。
// ならば・・・!
> public class A_0000 : A_0007 { }
. public class A_0001 : A_0000 { }
. public class A_0002 : A_0001 { }
. public class A_0003 : A_0002 { }
. public class A_0004 : A_0003 { }
. public class A_0005 : A_0004 { }
. public class A_0006 : A_0005 { }
. public class A_0007 : A_0006 { }
// ↑たくさん追加してみた
// 実行!
(1,14): error CS0146: 'A_0007' と 'A_0000' を含む、循環する基底クラスの依存関係です。
(2,14): error CS0146: 'A_0000' と 'A_0001' を含む、循環する基底クラスの依存関係です。
(3,14): error CS0146: 'A_0001' と 'A_0002' を含む、循環する基底クラスの依存関係です。
(4,14): error CS0146: 'A_0002' と 'A_0003' を含む、循環する基底クラスの依存関係です。
(5,14): error CS0146: 'A_0003' と 'A_0004' を含む、循環する基底クラスの依存関係です。
+ 追加の 3 errors
// うん、エラー。
// あ、エラーは5つまで表示して、その後は、「+追加の~~」て表示されるのか。
// インターフェースは?
> public interface A_0000 : A_0007 { }
. public interface A_0001 : A_0000 { }
. public interface A_0002 : A_0001 { }
. public interface A_0003 : A_0002 { }
. public interface A_0004 : A_0003 { }
. public interface A_0005 : A_0004 { }
. public interface A_0006 : A_0005 { }
. public interface A_0007 : A_0006 { }
(1,18): error CS0529: 継承インターフェイス 'A_0007' により、'A_0000' のインターフェイス階層内で循環参照が発生します。
(2,18): error CS0529: 継承インターフェイス 'A_0000' により、'A_0001' のインターフェイス階層内で循環参照が発生します。
(3,18): error CS0529: 継承インターフェイス 'A_0001' により、'A_0002' のインターフェイス階層内で循環参照が発生します。
(4,18): error CS0529: 継承インターフェイス 'A_0002' により、'A_0003' のインターフェイス階層内で循環参照が発生します。
(5,18): error CS0529: 継承インターフェイス 'A_0003' により、'A_0004' のインターフェイス階層内で循環参照が発生します。
+ 追加の 3 errors
// .................やっぱり、ダメだった。。。
// 完。

今日のC#インタラクティブ (2017/06/15) ~StructLayout編~

こんにちは、Takymです。
C#インタラクティブの時間です。

> using System.Runtime.InteropServices;
// ↑ちゃんとusingしておこう。
> [StructLayout(LayoutKind.Explicit)]
. struct TEST {
. 	[FieldOffset(0)]
. 	ulong UInt32Value;
. 	[FieldOffset(0)]
. 	long SInt32Value;
. 	[FieldOffset(0)]
. 	double DoubleValue;
. 	[FieldOffset(0)]
. 	bool FlagValue;
. }
// よし、構造体はこんな実装でいいかな。
// 初期値を設定しよう。
> TEST t = new TEST();
> t.UInt32Value = 0x12345678;
(1,3): error CS0122: 'TEST.UInt32Value' はアクセスできない保護レベルになっています
// ↑あ、ちょっと失敗した。
// 全部publicにして・・・
> [StructLayout(LayoutKind.Explicit)]
. struct TEST
. {
. 	[FieldOffset(0)]
. 	public ulong UInt32Value;
. 	[FieldOffset(0)]
. 	public long SInt32Value;
. 	[FieldOffset(0)]
. 	public double DoubleValue;
. 	[FieldOffset(0)]
. 	public bool FlagValue;
. }
> TEST t = new TEST();
> t.UInt32Value = 0x12345678;
// これでどうだ!
// うん、問題なし。
> t
[Submission#4+TEST]
// あ、そういえば、ToStringを実装しなきゃいけなかったね・・・
// もう一度、実装
> [StructLayout(LayoutKind.Explicit)]
. struct TEST
. {
. 	[FieldOffset(0)]
. 	public ulong UInt32Value;
. 	[FieldOffset(0)]
. 	public long SInt32Value;
. 	[FieldOffset(0)]
. 	public double DoubleValue;
. 	[FieldOffset(0)]
. 	public bool FlagValue;
.
. 	public override string ToString()
. 	{
. 		return $"UInt32Value:{UInt32Value},SInt32Value:{SInt32Value},DoubleValue:{DoubleValue},FlagValue:{FlagValue}";
. 	}
. }
// 流石にもう何もないよね・・・
> TEST t = new TEST();
> t.UInt32Value = 0x12345678;
> t
[UInt32Value:305419896,SInt32Value:305419896,DoubleValue:1.50897478170006E-315,FlagValue:True]
// なんか少数が複雑だなぁ
// falseを入れてみよう
> t.FlagValue = false;
> t
[UInt32Value:305419776,SInt32Value:305419776,DoubleValue:1.50897418882129E-315,FlagValue:False]
// 少し変わった。
// 1.5だとどうなる!?
> t.DoubleValue = 1.5;
> t
[UInt32Value:4609434218613702656,SInt32Value:4609434218613702656,DoubleValue:1.5,FlagValue:False]
// 整数値が!?
// 1
> t.SInt32Value = 1;
> t
[UInt32Value:1,SInt32Value:1,DoubleValue:4.94065645841247E-324,FlagValue:True]
// おお!FlagValueがtrueになった!

今回はここまでです。

C#で拡張子をレジストリに登録する

こんにちは、Takymです。
以前に、C#のMicrosoft.Win32.RegistryKeyクラスを使用して拡張子登録 という記事を書いた事があります。
今回はそのリメイク版みたいな物です。

登録の仕方

まず、拡張子をレジストリに登録する方法を簡単に説明します。
HKEY_CLASSES_ROOTに、「.xxx」というキーを作成します。
xxxは拡張子の名前です。必ずドット(.)から始めます。
次に、作成したキーの限定の所に任意の文字列を入れます。
そしたら、その文字列と同じ名前で、HKEY_CLASSES_ROOT内にキーを作成します。
作成したキーの限定の値を変更すると、エクスプローラの種類の所に表示される文字列を変更する事ができます。
次に、そのキーにshellキーを作成してその中にopenキーを作成します。
さらにopenキーの中にcommandキーを作成します。
commandキーの限定を特定のコマンドラインに変更すれば拡張子の登録は完了です。

サンプルソース

C#でレジストリを変更するには、Microsoft.Win32.RegistryKeyクラスを使用します。

using System;
using System.Collections.Generic;
using Microsoft.Win32;
namespace Test
{
/// <summary>
///  ファイル拡張子を管理する為のクラスです。
/// </summary>
public class FileExtension : IDisposable
{
/// <summary>
///  変更する拡張子です。先頭に<c>"."</c>を付けません。
/// </summary>
public string Extension { get; }
/// <summary>
///  拡張子の説明です。エクスプローラの種類に表示される文字列です。
/// </summary>
public string Description { get; set; }
/// <summary>
///  ファイルアイコンのファイルパスです。
/// </summary>
public string IconPath { get; set; }
/// <summary>
///  アイコンインデックスです。
/// </summary>
public int IconIndex = -1;
/// <summary>
///  拡張子の動詞の一覧です。
/// </summary>
public Dictionary<string, (string Command, string Description)> Verbs { get; }
/// <summary>
///  オブジェクトが破棄されているかどうかを取得します。
/// </summary>
protected bool IsDisposed { get; private set; }
private RegistryKey _key_b, _key_ico, _key_shell;
/// <summary>
///  操作する拡張子を指定して、新しいインスタンスを生成します。
/// </summary>
/// <param name="ext">変更する拡張子です。先頭に<c>"."</c>を付けません。</param>
public FileExtension(string ext)
{
this.IsDisposed = false;
this.Extension = ext;
this.Verbs = new Dictionary<string, (string Command, string Description)>();
using (var _key_a = Registry.ClassesRoot.CreateSubKey("." + ext, true)) {
string _key_name = (string)(_key_a.GetValue(null, ext + "_auto_file"));
_key_a.SetValue(null, _key_name);
_key_b = Registry.ClassesRoot.CreateSubKey(_key_name, true);
_key_ico = _key_b.CreateSubKey("DefaultIcon", true);
_key_shell = _key_b.CreateSubKey("shell", true);
}
}
/// <summary>
///  現在のオブジェクトの内容をレジストリに保存します。
/// </summary>
public void Save()
{
if (IsDisposed) throw new ObjectDisposedException(nameof(FileExtension));
_key_b.SetValue(null, this.Description);
_key_ico.SetValue(null, $"\"{this.IconPath}\"" + (IconIndex >= 0 ? ", " + IconIndex : string.Empty));
foreach (var item in this.Verbs) {
using (var _key_c = _key_shell.CreateSubKey(item.Key, true))
using (var _key_d = _key_c.CreateSubKey("command", true)) {
_key_c.SetValue(null, item.Value.Description);
_key_d.SetValue(null, item.Value.Command);
}
}
}
/// <summary>
///  このオブジェクトのファイナライザーです。
/// </summary>
~FileExtension()
{
this.Dispose(false);
}
/// <summary>
///  このオブジェクトで使用している全てのリソースを開放します。
/// </summary>
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
///  このオブジェクトのインスタンスを破棄させます。
/// </summary>
/// <param name="disposing">
///  このクラス内に存在する、他の<see cref="System.IDisposable"/>も破棄するかどうかです。
/// </param>
protected virtual void Dispose(bool disposing)
{
if (!IsDisposed) {
if (disposing) {
_key_b.Close();
_key_ico.Close();
_key_shell.Close();
}
this.Description = null;
this.IconPath = null;
IconIndex = 0;
this.Verbs.Clear();
IsDisposed = true;
}
}
}
}

このプログラムを以下の様に呼び出します。

using (FileExtension fe = new FileExtension("ext")) {
fe.Description = "拡張子登録の実験 (電卓を開くだけのファイル)";
fe.IconPath = @"C:\Windows\System32\calc.exe";
fe.IconIndex = 0;
fe.Verbs.Add("open", (@"C:\Windows\System32\calc.exe", "電卓を開く"));
fe.Save();
}

このプログラムを実行すると、extファイルを開くと電卓が開かれるようになります。

感想

昔書いたプログラムをもう一度書き直してみると、昔書いたプログラムより見やすく書ける事が分かりました。
(※この記事はリメイク版)
間違いの指摘、誤字・脱字、分からない事等はこの記事のコメント欄にお願いします。
最後まで読んでくださってありがとうございました。また次回も読んでくれると嬉しいです。

今日のC#インタラクティブ (2017/06/10) ~隠しキーワード編~

こんにちは、Takymです。
C#インタラクティブのコーナーです。
隠しキーワードについて説明しているサイトを見つけて面白そうだったので、C# インタラクティブでも使えるのかと思いやってみる事にしました。
見つけたサイト:型付き参照 – C# によるプログラミング入門 | ++C++; // 未確認飛行 C

> int a = 123;
> TypedReference tr = __makeref(a);
(1,1): error CS0610: フィールドまたはプロパティに型 'TypedReference' を指定することはできません。
// ↑ え? やっぱり、使えないのか・・・
> object obj = __makeref(a);
(1,14): error CS0029: 型 'System.TypedReference' を 'object' に暗黙的に変換できません
// !? System.TypedReferenceはobjectじゃない、だと・・・
> void* ptr = __makeref(a);
(1,1): error CS0214: ポインターおよび固定サイズ バッファーは、unsafe コンテキストでのみ使用することができます。
(1,13): error CS0029: 型 'System.TypedReference' を 'void*' に暗黙的に変換できません
// unsafeにするの忘れたけど・・・、っていうかSystem.TypedReferenceって何物だ!?
// 諦めよう・・・

今回はここまでです。
最後まで読んでくれてありがとうございました。

今日のC#インタラクティブ (2017/06/08) ~ベンチマークプログラム編~

こんにちは、Takymです。
今回は、VS2017とcsi.exeのC#インタラクティブでどちらが早いか競争したいと思います。

今回、実行するプログラム

TimeSpan DoSomething()
{
DateTime dt0 = DateTime.Now;
string a = string.Empty;
int i;
for (i = 0; i  0; --i) {
a += i;
}
return DateTime.Now - dt0;
}

「重い処理」を実行して、その時間を図るベンチマークプログラムです。

10回実行した結果

[00:00:00.1093941]
[00:00:00.1562317]
[00:00:00.1562719]
[00:00:00.1406275]
[00:00:00.1093770]
[00:00:00.1093578]
[00:00:00.0937732]
[00:00:00.0937492]
[00:00:00.0937151]
[00:00:00.0937535]
// 平均:115.6251ミリ秒
[00:00:00.0937406]
[00:00:00.0624847]
[00:00:00.0625167]
[00:00:00.0625009]
[00:00:00.0468757]
[00:00:00.0625014]
[00:00:00.0625009]
[00:00:00.0625000]
[00:00:00.0625014]
[00:00:00.0625017]
// 平均:64.0624ミリ秒

csi.exeの方が速いですね。約二倍くらいの違いです。
しかし、結果が少しばらついているので、運にもよるかもしれません。
今回は、ここまでです。最後まで読んでくれてありがとうございました。
分からない事・間違い・誤字・脱字等はこの記事のコメント欄にお願いします。

今日のC#インタラクティブ (2017/06/07) ~構造体編~

こんにちは、Takymです。
今日のC#インタラクティブのコーナーです。
今回は構造体編です。

// さっそく構造体を書く。
> struct Test
. {
. 	public ulong Value;
. 	public bool IsMasked { get; private set; }
.
. 	public Test(ulong value)
. 	{
. 		Value = value;
. 		IsMasked = false;
. 	}
.
. 	public Test GetMaskedValue()
. 	{
. 		Test result = new Test();
. 		result.Value = ~this.Value;
. 		result.IsMasked = !this.IsMasked;
. 		return result;
. 	}
. }
// 構造体のインスタンスを生成。
> Test t = new Test(123);
// 値表示
> t
[Submission#2+Test]
// ↑あれ?
// ToStringをオーバーライドしてみる
> struct Test
. {
. 	public ulong Value;
. 	public bool IsMasked { get; private set; }
.
. 	public Test(ulong value)
. 	{
. 		Value = value;
. 		IsMasked = false;
. 	}
.
. 	public Test GetMaskedValue()
. 	{
. 		Test result = new Test();
. 		result.Value = ~this.Value;
. 		result.IsMasked = !this.IsMasked;
. 		return result;
. 	}
.
. 	public override string ToString()
. 	{
. 		ulong realvalue = this.IsMasked ? ~this.Value : this.Value;
. 		return $"{this.Value}(real-value: {realvalue})";
. 	}
. }
// よし、もういちど
> Test t = new Test(123);
> t
[123(real-value: 123)]
// ↑おお、成功した!
// 反転させてみる。
> t.GetMaskedValue()
[18446744073709551492(real-value: 123)]
// うまくいっている。
// 最後にもう一つ。
> t.GetMaskedValue().GetMaskedValue()
[123(real-value: 123)]

今回は、ここまでです。
構造体を書いたので長く感じた方もいらっしゃると思いますが、今回も内容は薄いですね。
最後まで読んでくれてありがとうございました。

Make Font Windows GUI 裏技編

こんにちは、Takymです。
今回は、この前作ったアプリのMake Font Windows GUIのちょっとした裏技と隠しコマンドを紹介したいと思います。
ダウンロード→http://takymsystems.blog.fc2.com/blog-entry-19.html

C&Pの裏技

実は編集中にコピーボタンを押すと、以下の様なアスタリスク(*)とドット(.)だけのテキストがグリップボードにコピーされます。

........
........
..***...
.*...*..
*.....*.
*.*.*.*.
*.*.*.*.
*.....*.
*.....*.
*.*.*.*.
*..*..*.
.*...*..
..***...
........
........
........

裏技を使ったコピペのやり方

1. コピーボタンを押します。

(※写真のフォントはHaribote OSの5日目のフォントです。)
2. 適当なテキストエディタにCtrl+V等で貼り付ける。

3. 少し編集する。

4. エディタに貼り付ける。

5. 結果

隠しコマンド

Make Font Windows GUIの隠しコマンドを紹介します。
Ctrl+Alt+Shift+Esc : アプリ終了
Ctrl+S : 上書き保存
Ctrl+L : フォントファイルの再読み込み
Alt+F1 : コンパイル
Alt+F2 : ファイル選択
Alt+F3 : フォントファイルの再読み込み
Alt+F4 : 上書き保存
今回はここまでです。
最後まで読んでくれてありがとうございました。

今度、PHPとかJavaScriptとか使って、ブログとWikiを融合させたWebサービスを作りたいな。

こんにちは、Takymです。
これは、ただのメモ書きみたいな物です。
いつか、ブログとWikiを融合させた、Webサービスを作りたいなと思いました。
(※いつになるか分からない)

続きを読む “今度、PHPとかJavaScriptとか使って、ブログとWikiを融合させたWebサービスを作りたいな。”

今日のC#インタラクティブ (2017/06/03) ~どうしてもコマンドプロンプトと融合させたい編~

こんにちは、Takymです。
今回は、C#インタラクティブのウィンドウ内でコマンドプロンプトの画面を表示させたいと思います。

// この前はProcess.Startで失敗した。
// そもそもConsole.ReadLine()は使えるのか。
> Console.ReadLine()
// ................
// ................
// ................
// ................
// ................
// ・・・・・・・・?
// ・・・固まってしまった。。。
// どうやら、C# インタラクティブは標準入力に対応してないようです。
// 一応、csi.exeで試してみる。
> Console.ReadLine()
test
"test"
// できた!
// csi.exe版ではできるようです。
// と、言う事は・・・!
> Process.Start("cmd")
[System.Diagnostics.Process (cmd)]
// ・・・別のウィンドウで開きましたorz......................

今回はここまでです。
最後まで読んでくれてありがとうございました。

WordPress.com で次のようなサイトをデザイン
始めてみよう