トップページに戻る
C# LINQメモ
C#で作ったツール(コンソールアプリ)
C#メモ
目次
001 ローカル変数の初期化のタイミング
using System;
class Program
{
static void Main()
{
for (int I = 1; I <= 3; I++) {
int X = 1;
X++;
Console.WriteLine(X);
}
}
}
//出力結果
2
2
2
002 アイコンバーと外部ツールの設定
C# 2008 Express (画面解像度が1024*768)
VS2013 (画面解像度が1280*1024)
VS2017 Express (画面解像度が1920*1080)
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
外部ツールで、フリー版EmEditorを最大化して起動するWinFormExeのソース
using System;
using System.Windows.Forms;
namespace WinForm
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
string AddCmdLine = "";
string[] wkArr = Environment.GetCommandLineArgs();
for (int I = 1; I <= wkArr.GetUpperBound(0); I++) {
AddCmdLine += wkArr[I];
if (I < wkArr.GetUpperBound(0)) AddCmdLine += " ";
}
var hPsInfo = new System.Diagnostics.ProcessStartInfo();
hPsInfo.FileName = @"C:\Program Files\EmEditor\EmEditor.exe";
hPsInfo.Arguments = AddCmdLine;
hPsInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Maximized;
System.Diagnostics.Process.Start(hPsInfo);
this.Close();
}
}
}
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
EmEditorの代わりにサクラエディタを使用する場合
003 DataTableの作成とか
class Program
{
static void Main()
{
var dt = new System.Data.DataTable();
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("Val", typeof(string));
dt.Rows.Add(0, "aaa");
dt.Rows.Add(1, "bbb");
dt.Rows.Add(2, "ccc");
dt.Rows.Add(3, "ddd");
//インデクサ経由での書き換え
dt.Rows[0]["ID"] = 333;
//dt.Rows[3].Delete();
//dt.Rows.RemoveAt(3);
dt.Columns.Add("Added", typeof(int));
string wk = dt.Rows[0]["Added"].GetType().Name;
if (dt.Rows[0]["Added"] is DBNull) {
Console.WriteLine("nullです");
}
else Console.WriteLine("nullでない");
}
}
004 DBから取得した値をintに変換
using System;
class Program
{
static void Main(string[] args)
{
string work = "123";
object target = work;
int conved = Convert.ToInt32(target);
Console.WriteLine("変換後の値は{0}", conved);
var dt = new System.Data.DataTable();
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("Val", typeof(string));
dt.Rows.Add(0, "aaa");
dt.Rows.Add(1, "bbb");
dt.Rows[0]["ID"] = 333;
conved = Convert.ToInt32(dt.Rows[0]["ID"]);
Console.WriteLine("変換後の値は{0}", conved);
conved = int.Parse(dt.Rows[0]["ID"].ToString());
Console.WriteLine("変換後の値は{0}", conved);
}
}
005 SJISでバイト数を指定して切り出し
using System;
using System.Text;
class Program
{
static void Main(string[] args)
{
string wk;
//wk = "111111111122222222223333333333444444444455555555556";
//wk = "11111111112222222222333333333344444444445555555555";
//wk = "11111222223333344444555556";
//wk = "1111122222333334444455555";
//wk = "1234567890";
wk = "1234567890";
var sjisEnc = Encoding.GetEncoding("Shift_JIS");
byte[] byteArr = sjisEnc.GetBytes(wk);
if (byteArr.Length <= 50) {
Console.WriteLine("50バイト以下です");
Console.WriteLine(wk);
}
else {
string out1 = sjisEnc.GetString(byteArr, 0, 50);
string out2 = sjisEnc.GetString(byteArr, 50, byteArr.Length - 50);
Console.WriteLine("50バイトより多いです");
Console.WriteLine(out1);
Console.WriteLine(out2);
}
}
}
006 System.IO.Path.Combineのサンプル
class Program
{
static void Main()
{
string wk1 = "";
string wk2 = "";
wk1 = System.IO.Path.Combine(@"D:\WorkFile", "subFolder");
wk2 = System.IO.Path.Combine(wk1, "textFile.txt");
System.Console.WriteLine(wk1);
System.Console.WriteLine(wk2);
}
}
//出力結果
D:\WorkFile\subFolder
D:\WorkFile\subFolder\textFile.txt
007 Array.IndexOfジェネリックメソッドのサンプル
using System;
class Program
{
static void Main()
{
int[] arr = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
if (Array.IndexOf<int>(arr, 10) == -1) {
Console.WriteLine("10は存在しません");
}
else Console.WriteLine("10は存在します");
}
}
//出力結果
10は存在します
008 System.IO.File.WriteAllLinesのサンプル
@IT --- テキスト・ファイルの内容を簡単に書き込むには?
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
var WillOut = new List<string>();
WillOut.Add("1行目");
WillOut.Add("2行目");
System.IO.File.WriteAllLines(@"D:\aaa.txt", WillOut.ToArray(),
System.Text.Encoding.GetEncoding("Shift_JIS"));
}
}
009 ExcelのR1C1形式の列番号をA1形式の列名称に変換
using System;
using System.Linq;
class Program
{
static void Main()
{
try {
foreach (int Any in Enumerable.Range(1, 16384)) {
Console.WriteLine("列番号{0,5}は、列名称{1,5}", Any, getA1(Any));
}
}
catch (Exception ex) {
Console.WriteLine(ex.StackTrace);
}
}
static string getA1(int target)
{
string WillReturn = "";
for (int I = 1; I <= target; I++) {
if (I == 1) {
WillReturn = "A";
continue;
}
int AddPlace = WillReturn.Length - 1;
while (true) {
if (AddPlace == -1) {
WillReturn = "A" + WillReturn;
break;
}
if (WillReturn[AddPlace] != 'Z') {
WillReturn = WillReturn.Insert(AddPlace, ((char)(WillReturn[AddPlace] + 1)).ToString());
WillReturn = WillReturn.Remove(AddPlace + 1, 1);
break;
}
if (WillReturn[AddPlace] == 'Z') {
WillReturn = WillReturn.Insert(AddPlace, "A");
WillReturn = WillReturn.Remove(AddPlace + 1, 1);
AddPlace--;
continue;
}
}
}
return WillReturn;
}
}
//出力結果
列番号 1は、列名称 A
列番号 2は、列名称 B
列番号 3は、列名称 C
省略
列番号 25は、列名称 Y
列番号 26は、列名称 Z
列番号 27は、列名称 AA
省略
列番号16382は、列名称 XFB
列番号16383は、列名称 XFC
列番号16384は、列名称 XFD
010 オブジェクトのシリアライズ
DOBON --- オブジェクトの内容をバイナリファイルに保存、復元する
tekkの日記 C#,VB.NET --- BinaryFormatterを使用してインスタンスをバイナリでシリアライズする。
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
[Serializable()]
class TestClass
{
internal int Member1;
internal string Member2;
internal string ToString(){
return string.Format("Member1={0},Member2={1},HashCode={2}",
Member1,Member2,GetHashCode());
}
}
class Program
{
static void Main()
{
var InsTestClass1 = new TestClass() { Member1 = 123, Member2 = "abc" };
TestClass InsTestClass2;
var bf1 = new BinaryFormatter();
byte[] ArrByte;
using (var ms1 = new MemoryStream()) {
bf1.Serialize(ms1, InsTestClass1);
ArrByte = ms1.ToArray();
}
using (var ms2 = new MemoryStream()) {
ms2.Position = 0;
ms2.Write(ArrByte, 0, ArrByte.Length);
var bf2 = new BinaryFormatter();
ms2.Position = 0;
InsTestClass2 = (TestClass)(bf2.Deserialize(ms2));
}
Console.WriteLine(InsTestClass1.ToString());
Console.WriteLine(InsTestClass2.ToString());
}
//出力結果
//Member1=123,Member2=abc,HashCode=58225482
//Member1=123,Member2=abc,HashCode=33574638
}
011 ラムダ式の変数キャプチャ機能に関する実験
ラムダ式の変数キャプチャ機能で
キャプチャした変数は、参照渡しのようです。
using System;
class Program
{
static void Main()
{
int I = 0;
Action act = () => I++;
act();
act();
act();
Console.WriteLine("I={0}", I); //I=3
}
}
012 深さ優先探索の雛形
バックトラック問題でよく使う深さ優先探索の雛形です。
using System;
using System.Collections.Generic;
class Program
{
private struct JyoutaiDef
{
internal int Level;
}
static void Main()
{
var stk = new Stack<JyoutaiDef>();
JyoutaiDef WillPush;
//WillPushを加工
stk.Push(WillPush);
int AnswerCnt = 0;
while (stk.Count > 0) {
JyoutaiDef Popped = stk.Pop();
if (true) { //解の条件を満たしたら
//解を出力
continue;
}
//Poppedを基にしてWillPushを加工
stk.Push(WillPush);
}
}
//解であるかを判定
static bool IsOK(int X, int Y, string Path)
{
return true;
}
//有効な状態かを判定
static bool IsValid(int X, int Y, string Path)
{
return true;
}
}
013 匿名関数の即時実行
ActionやFuncを匿名でかっこ良く書くお話
FuncデリゲートもしくはPredicateデリゲートと組み合わせると便利そうです。
Actionデリゲートでは、あまり使い道がなさそう
using System;
class Program
{
static void Main()
{
for (int I = 1; I <= 4; I++) {
Console.WriteLine(
new Func<int, string>(X =>
{
if (X == 1) return "1です。";
if (X == 2) return "2です。";
return "3以上です。";
})(I));
}
Console.WriteLine();
for (int I = 1; I <= 4; I++) {
Console.WriteLine(I.ToString() + "の偶数判定結果=" +
new Predicate<int>(X =>
{
if (X % 2 == 0) return true;
return false;
})(I));
}
}
}
//出力結果
1です。
2です。
3以上です。
3以上です。
1の偶数判定結果=False
2の偶数判定結果=True
3の偶数判定結果=False
4の偶数判定結果=True
014 Predicate,Func,Actionデリゲートのラムダ式でキャプチャされた引数は参照渡しだが、引数は値渡し
MSDN --- Func<T, TResult> デリゲート
つまり、カプセル化されるメソッドは、値渡しされる単一のパラメータを受け取ること、
および、戻り値を持つことが必要です。
MSDN --- Action<T> デリゲート
つまり、カプセル化されるメソッドは、値渡しされる単一のパラメータを受け取ること、
および、戻り値を持たないことが必要です
using System;
class Program
{
static void Main()
{
int キャプチャ変数 = 0;
int 実引数 = 0;
Predicate<int> TestPred = (仮引数) => {
仮引数++;
キャプチャ変数++;
return true;
};
Func<int, bool> TestFunc = (仮引数) => {
仮引数++;
キャプチャ変数++;
return true;
};
Action<int> TestAct = 仮引数 => {
仮引数++;
キャプチャ変数++;
};
TestPred(実引数);
TestFunc(実引数);
TestAct(実引数);
Console.WriteLine("実引数={0}", 実引数);
Console.WriteLine("キャプチャ変数={0}", キャプチャ変数);
}
}
//出力結果
実引数=0
キャプチャ変数=3
015 Checkedステートメントでダウンキャスト時のオーバフロー検知
using System;
class Program
{
static void Main()
{
try {
long wkLong1 = (long)int.MaxValue * 3;
int wkInt1 = (int)wkLong1;
Console.WriteLine(wkInt1);
checked {
long wkLong2 = (long)int.MaxValue * 3;
int wkInt2 = (int)wkLong2;
Console.WriteLine(wkInt2);
}
}
catch (Exception ex) {
Console.WriteLine("例外が発生しました。");
Console.WriteLine(ex.Message);
}
}
}
//出力結果
2147483645
例外が発生しました。
算術演算の結果オーバーフローが発生しました。
016 実行アセンブリのあるフォルダにあるテキストファイルのフルパスを取得
//using System.Reflection; が必要
string txtFileFullPath = Assembly.GetExecutingAssembly().Location;
txtFileFullPath = System.IO.Path.GetDirectoryName(txtFileFullPath);
txtFileFullPath = System.IO.Path.Combine(txtFileFullPath, "テキストファイル名");
017 参照渡しのOutとRefの違い
Refの場合は、変数を初期化してからメソッドの引数とする必要がある。
Outの場合は、メソッド内で値を割り当てる必要がある。
018 Dictionaryをforeach文で列挙するサンプル
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
var TestDict = new Dictionary<int, string>();
TestDict.Add(111, "AAA");
TestDict.Add(222, "BBB");
TestDict.Add(333, "CCC");
Console.WriteLine("■■■列挙方法1■■■");
foreach (KeyValuePair<int, string> EachPair in TestDict) {
Console.WriteLine("TestDict[{0}] = {1}", EachPair.Key, EachPair.Value);
}
Console.WriteLine();
Console.WriteLine("■■■列挙方法2■■■");
foreach (var EachPair in TestDict) {
Console.WriteLine("TestDict[{0}] = {1}", EachPair.Key, EachPair.Value);
}
Console.WriteLine();
Console.WriteLine("■■■列挙方法3■■■");
foreach (int EachKey in TestDict.Keys) {
Console.WriteLine("TestDict[{0}] = {1}", EachKey, TestDict[EachKey]);
}
Console.WriteLine();
Console.WriteLine("■■■列挙方法4■■■");
foreach (string EachValue in TestDict.Values) {
Console.WriteLine("任意のキーのValue = {0}", EachValue);
}
}
}
//出力結果
■■■列挙方法1■■■
TestDict[111] = AAA
TestDict[222] = BBB
TestDict[333] = CCC
■■■列挙方法2■■■
TestDict[111] = AAA
TestDict[222] = BBB
TestDict[333] = CCC
■■■列挙方法3■■■
TestDict[111] = AAA
TestDict[222] = BBB
TestDict[333] = CCC
■■■列挙方法4■■■
任意のキーのValue = AAA
任意のキーのValue = BBB
任意のキーのValue = CCC
019 プロジェクトの設定でのCheckedの代用
ビルド → 詳細設定 → 演算のオーバーフローおよびアンダーフローのチェック
をチェックする。
ただし浮動小数点型の場合は、オーバーフローおよびアンダーフロー例外が発生しないです。
020 LINQのAggregateメソッド と string.Joinメソッド の比較
string.Joinメソッドのほうが文字数が少ないですね
string.Joinメソッドは、
C#4.0からは、配列でなくて列挙でもいいです。
using System;
using System.Linq;
class Program
{
static void Main()
{
string[] wkStrArr = { "A", "B", "C", "D", "E", "F" };
Console.WriteLine(wkStrArr.Aggregate((A, B) => A + "■" + B));
Console.WriteLine(string.Join("■", wkStrArr));
}
}
//出力結果
A■B■C■D■E■F
A■B■C■D■E■F
021 LINQのSelectメソッド と Array.ConvertAllメソッド の比較
Array.ConvertAllメソッドは、たまには使えそうですね。
using System;
using System.Linq;
class Program
{
static void Main()
{
int[] wkIntArr = Enumerable.Range(1, 5).ToArray();
string[] wkStrArr1 = Array.ConvertAll(wkIntArr, X => X.ToString());
string[] wkStrArr2 = wkIntArr.Select(X => X.ToString()).ToArray();
Console.WriteLine(string.Join("■", wkStrArr1));
Console.WriteLine(string.Join("■", wkStrArr2));
}
}
//出力結果
1■2■3■4■5
1■2■3■4■5
022 構造体のListジェネリックのDistinct
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
struct TestStruct
{
internal int Val1;
internal int Val2;
}
static void Main()
{
var TestList1 = new List<TestStruct>();
TestList1.Add(new TestStruct() { Val1 = 1, Val2 = 1 });
TestList1.Add(new TestStruct() { Val1 = 1, Val2 = 1 });
TestList1.Add(new TestStruct() { Val1 = 1, Val2 = 2 });
TestList1.Add(new TestStruct() { Val1 = 1, Val2 = 2 });
TestList1.Add(new TestStruct() { Val1 = 2, Val2 = 1 });
TestList1.Add(new TestStruct() { Val1 = 2, Val2 = 1 });
TestList1.Add(new TestStruct() { Val1 = 2, Val2 = 2 });
TestList1.Add(new TestStruct() { Val1 = 2, Val2 = 2 });
var TestList2 = new List<TestStruct>(TestList1);
var TestList3 = new List<TestStruct>(TestList1);
//LINQのGroupByを、Distinctの代わりに使う方法
TestList1 = TestList1.GroupBy(X => new { X.Val1, X.Val2 })
.Select(X => new TestStruct { Val1 = X.Key.Val1, Val2 = X.Key.Val2 }).ToList();
//FindIndexを使う方法
for (int I = TestList2.Count - 1; 1 <= I; I--) {
if (TestList2.FindIndex(0, I,
X => X.Val1 == TestList2[I].Val1
&& X.Val2 == TestList2[I].Val2) >= 0)
TestList2.RemoveAt(I);
}
//2重ループを使う方法
for (int I = TestList3.Count - 1; 1 <= I; I--) {
for (int J = 0; J <= I - 1; J++) {
if (TestList3[I].Val1 == TestList3[J].Val1
&& TestList3[I].Val2 == TestList3[J].Val2) {
TestList3.RemoveAt(I);
break;
}
}
}
foreach (var EachTestStruct in TestList1) {
Console.WriteLine("Val1={0},Val2={1}",
EachTestStruct.Val1, EachTestStruct.Val2);
}
Console.WriteLine(TestList1.SequenceEqual(TestList2));
Console.WriteLine(TestList1.SequenceEqual(TestList3));
}
}
023 Listジェネリックでの降順ソートの方法
LinqのOrderByDescendingメソッドだと安定したソートなのに対し、
ListジェネリックのSortメソッドは、安定でないソートなので、
処理速度は、こっちのほうが速そうですね。
なお、B-Aではなく、B.CompareTo(A)と記述すれば、アンダフロー対策になります。
using System;
using System.Linq;
class Program
{
static void Main()
{
var wkList = Enumerable.Range(1, 5).ToList();
wkList.Sort((A, B) => B.CompareTo(A));
wkList.ForEach(X => Console.WriteLine(X));
}
}
//出力結果
5
4
3
2
1
配列の場合も同様です。
var wkArr = Enumerable.Range(1, 5).ToArray();
Array.Sort(wkArr, (A, B) => B.CompareTo(A));
Array.ForEach(wkArr, X => Console.WriteLine(X));
024 配列とListジェネリックのReverseメソッド
LINQではなく、Listジェネリックのメソッドとして存在します。
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
var wkList = new List<char>() { '1', '9', 'Z', 'A' };
wkList.Reverse();
wkList.ForEach(X => Console.Write("{0}■", X));
//出力
//A■Z■9■1■
Console.WriteLine();
char[] wkArr = {'2', '8', 'Y', 'B' };
Array.Reverse(wkArr);
Array.ForEach(wkArr, X => Console.Write("{0}■", X));
//出力
//B■Y■8■2■
}
}
025 ネストを深くしないUsing指定
using System;
using System.IO;
class Program
{
static void Main()
{
//違う型なら、複数にusing指定が必要
using (var sr1 = new StreamReader(@"C:\test.txt"))
using (var sw1 = new StreamWriter(@"C:\test.txt")) {
}
//同じ型ならまとめることが可能(ただしvarは使えない)
using (StreamReader sr2 = new StreamReader(@"C:\test.txt"),
sr3 = new StreamReader(@"C:\test.txt")){
}
}
}
026 乱数の使い方
using System;
class Program
{
static void Main()
{
for (int LoopSeed = 1; LoopSeed <= 10; LoopSeed++) {
var Rnd = new Random(LoopSeed);
//0以上5未満の整数をランダムに返す
int wkInt1 = Rnd.Next(5);
//1以上5以下の整数をランダムに返す
int wkInt2 = Rnd.Next(1, 5 + 1);
Console.WriteLine("0以上5未満の乱数={0} 1以上5以下の乱数={1}",
wkInt1, wkInt2);
}
}
//出力結果
//0以上5未満の乱数=1 1以上5以下の乱数=1
//0以上5未満の乱数=3 1以上5以下の乱数=3
//0以上5未満の乱数=1 1以上5以下の乱数=4
//0以上5未満の乱数=4 1以上5以下の乱数=5
//0以上5未満の乱数=1 1以上5以下の乱数=2
//0以上5未満の乱数=4 1以上5以下の乱数=3
//0以上5未満の乱数=1 1以上5以下の乱数=5
//0以上5未満の乱数=4 1以上5以下の乱数=1
//0以上5未満の乱数=2 1以上5以下の乱数=3
//0以上5未満の乱数=4 1以上5以下の乱数=4
}
027 ショートカットの(lnkファイル)の起動
カレントフォルダの編集などカスタマイズしたショートカットをC#から起動したい時に使う
class Program
{
static void Main()
{
var InsProcessStartInfo = new System.Diagnostics.ProcessStartInfo();
InsProcessStartInfo.FileName = @"lnkファイルのフルパス";
System.Diagnostics.Process.Start(InsProcessStartInfo);
}
}
028 クリップボートのフルパスリストの取得
using System;
using System.Windows.Forms;
class Program
{
[STAThreadAttribute]
static void Main()
{
if (Clipboard.ContainsFileDropList()) {
//データを取得する(取得できなかった時はnull)
System.Collections.Specialized.StringCollection files = Clipboard.GetFileDropList();
//取得したファイル名を列挙する
foreach (string EachFullPath in files) {
Console.WriteLine(EachFullPath);
}
}
}
}
029 HashSetのIsSubsetOfメソッドで部分集合の判定
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
var InsHashSet1 = new HashSet<int>() { 1 }; // 1
var InsHashSet2 = new HashSet<int>() { 1, 2, 3 }; // 3以下の自然数の集合
if (InsHashSet1.IsSubsetOf(InsHashSet2)) {
Console.WriteLine("集合1は、3以下の自然数の集合の部分集合です");
}
}
}
030 10進数と2進数の相互変換
using System;
class Program
{
static void Main()
{
// 10進数を2進数に変換
string BinStr = Convert.ToString(255, 2);
// 2進数を10進数に変換
int IntVal1 = Convert.ToInt32("1010", 2);
// 10進数を16進数に変換
string HexStr = Convert.ToString(65535, 16);
// 16進数を10進数に変換
int IntVal2 = Convert.ToInt32("abcdef", 16);
}
}
031 STLのpartial_sort
C#でSTLのpartial_sortと同様の部分ソートを行うには、
Sortメソッドを使います。
IComparerインターフェースを実装したクラスを定義する必要があります。
using System;
using System.Collections.Generic;
class Program
{
private class SortClass : System.Collections.Generic.IComparer<int>
{
public int Compare(int a, int b)
{
return a.CompareTo(b);
}
}
static void Main()
{
var TestList = new List<int>();
TestList.Add(9);
TestList.Add(1);
TestList.Add(8);
TestList.Add(2);
TestList.Add(7);
TestList.Add(3);
TestList.Add(6);
TestList.Add(4);
var TestArr = TestList.ToArray();
// 配列で、添字0から3を、Valの昇順にソート
Array.Sort(TestArr, 0, 3 - 0 + 1, new SortClass());
// Listで、添字4から7を、Valの昇順にソート
TestList.Sort(4, 7 - 4 + 1, new SortClass());
Console.WriteLine("配列のソート結果");
Array.ForEach(TestArr, pX => Console.Write("{0},", pX));
Console.WriteLine();
// 1,2,8,9,7,3,6,4,
Console.WriteLine("Listのソート結果");
TestList.ForEach(pX => Console.Write("{0},", pX));
Console.WriteLine();
// 9,1,8,2,3,4,6,7,
}
}