20210329のC#に関する記事は8件です。

【C#】staticっていつ使えばいいの?何がいいの?

staticいつ使えばいいんですか?

積極的に使う気が起きなかったが、上司のソースコードを見ると各所に散見されたので
いつ使えばいいのか?どんなメリットがあるのか?という観点で調べた。
1. staticとは
2. staticは何がいいのか
3. staticの良くないところ
4. いつ使えば良いのか
5. staticの書き方
6. まとめ
7. 参照

1. staticとは

  • 修飾子。
  • 静的クラス・メンバーの宣言で使う。
    • 静的クラスの場合メンバーも静的にする。
    • 静的クラスの場合コンストラクターを含めることはできない。
  • メモリを静的に確保する。

メンバ変数にstaticをつけた場合、その変数がメモリ上のどこに配置されるかが固定される。
メモリ上の位置が固定されるということはどこからでもこの変数にアクセスできるということです。
[https://qiita.com/suin/items/0897adc7dc653b9c20de]

2. staticは何がいいのか

  • インスタンス化するより処理が早くなる。というかインスタンス化は相対的にメモリを圧迫する。
  • インスタンスメンバーが追加されない保証がされる。

    「静的クラスを使用する利点は、インスタンス メンバーが誤って追加されないことをコンパイラで確認できるという点です。
    コンパイラによって、このクラスのインスタンスを作成できないことが保証されます。」

  • staticにするとインスタンス参照せずに直でメンバーへアクセスできる。

  • クラス唯一のものであればstaticとするという使い方ができる。

下記のPersonクラスではnameやageはPerson毎に変わるが、scientifiName(学名)は必ずホモサピエンスとなるのでstaticとしている。これによりインスタンス化されて

例)

  class Person
  {
    public string name; // インスタンス化したPersonごとに変わる。
    public int age;     // 同上。
    public static string scientificName;// インスタンス化してもPersonは皆ホモサピエンスで変わらない。
  }

  Person p = new Person()
  p.name = "安倍 晋三"; 
  p.age  = 66;
  Person.scientificName = "Homo Sapiens";

3. staticの良くないところ

4. いつ使えば良いのか

  • 共通のメソッドを定義する場合
  • 共通のプロパティを定義する場合
  • 複数クラス間で共通のプロパティを共有したい場合

とは言え、副作用を考えると極力使いたくないしオブジェクト指向的でないと思います。
しかし、上記例のようにクラス唯一の変数であり、

5. staticの書き方

  static 型名 フィールド名
  // 例
  public class MyBaseC
  {
      public struct MyStruct
      {
          public static int x = 100;
      }
  }

クラスをstaticにした場合はスコープ内のメンバーもstaticとしなければならない。

アクセスする方法
  • 完全修飾名 (MyBaseC.MyStruct.x) を使用。 (同じスコープからその静的メンバーにアクセス可能でない限り) ##### これはできない
  • 静的なローカル変数化 (つまり、メソッドのスコープで宣言された変数) 。

6. まとめ

静的メンバーはアプリケーション起動時にメモリを確保し
、終了までメモリの割り当てが変更されない。
故にどこからでもアクセスできるようになる。

共通して使うメソッドや、クラス内で唯一の変数などに使う。

メソッドは特別staticにする利点は見つからなかった。変数はインスタンス化することで、本来一つしかないはずの情報が複数作られるのを防ぐことができる。

しかし、副作用があるため代替方法があるなら検討すべき。

間違いやツッコミあったら教えてください?

7. 参照

静的クラスと静的クラス メンバー
PHP: 静的メソッドは何のためにあるか?
わい、static変数とstaticメソッドについて熱く語る
プログラミング序論 11.記憶クラスとスコープ

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

staticっていつ使えばいいの?何がいいの?

staticいつ使えばいいんですか?

積極的に使う気が起きなかったが、上司のソースコードを見ると各所に散見されたので
いつ使えばいいのか?どんなメリットがあるのか?という観点で調べた。
1. staticとは
2. staticは何がいいのか
3. staticの良くないところ
4. いつ使えば良いのか
5. staticの書き方
6. まとめ
7. 参照

1. staticとは

  • 修飾子。
  • 静的クラス・メンバーの宣言で使う。
    • 静的クラスの場合メンバーも静的にする。
    • 静的クラスの場合コンストラクターを含めることはできない。
  • メモリを静的に確保する。

メンバ変数にstaticをつけた場合、その変数がメモリ上のどこに配置されるかが固定される。
メモリ上の位置が固定されるということはどこからでもこの変数にアクセスできるということです。
[https://qiita.com/suin/items/0897adc7dc653b9c20de]

2. staticは何がいいのか

  • インスタンス化するより処理が早くなる。というかインスタンス化は相対的にメモリを圧迫する。
  • インスタンスメンバーが追加されない保証がされる。

    「静的クラスを使用する利点は、インスタンス メンバーが誤って追加されないことをコンパイラで確認できるという点です。
    コンパイラによって、このクラスのインスタンスを作成できないことが保証されます。」

  • staticにするとインスタンス参照せずに直でメンバーへアクセスできる。

  • クラス唯一のものであればstaticとするという使い方ができる。

下記のPersonクラスではnameやageはPerson毎に変わるが、scientifiName(学名)は必ずホモサピエンスとなるのでstaticとしている。これによりインスタンス化されて

例)

  class Person
  {
    public string name; // インスタンス化したPersonごとに変わる。
    public int age;     // 同上。
    public static string scientificName;// インスタンス化してもPersonは皆ホモサピエンスで変わらない。
  }

  Person p = new Person()
  p.name = "安倍 晋三"; 
  p.age  = 66;
  Person.scientificName = "Homo Sapiens";

3. staticの良くないところ

4. いつ使えば良いのか

  • 共通のメソッドを定義する場合
  • 共通のプロパティを定義する場合
  • 複数クラス間で共通のプロパティを共有したい場合

とは言え、副作用を考えると極力使いたくないしオブジェクト指向的でないと思います。
しかし、上記例のようにクラス唯一の変数であり、

5. staticの書き方

  static 型名 フィールド名
  // 例
  public class MyBaseC
  {
      public struct MyStruct
      {
          public static int x = 100;
      }
  }

クラスをstaticにした場合はスコープ内のメンバーもstaticとしなければならない。

アクセスする方法
  • 完全修飾名 (MyBaseC.MyStruct.x) を使用。 (同じスコープからその静的メンバーにアクセス可能でない限り) ##### これはできない
  • 静的なローカル変数化 (つまり、メソッドのスコープで宣言された変数) 。

6. まとめ

静的メンバーはアプリケーション起動時にメモリを確保し
、終了までメモリの割り当てが変更されない。
故にどこからでもアクセスできるようになる。

共通して使うメソッドや、クラス内で唯一の変数などに使う。

メソッドは特別staticにする利点は見つからなかった。変数はインスタンス化することで、本来一つしかないはずの情報が複数作られるのを防ぐことができる。

しかし、副作用があるため代替方法があるなら検討すべき。

間違いやツッコミあったら教えてください?

7. 参照

静的クラスと静的クラス メンバー
PHP: 静的メソッドは何のためにあるか?
わい、static変数とstaticメソッドについて熱く語る
プログラミング序論 11.記憶クラスとスコープ

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[c#]preview言語バージョンを使う方法

Visual Studio 2019を使用しています。

スクリーンショット (57).png
Assembly-Csharpを右クリックします。

スクリーンショット (58).png
プロジェクトのアンロードを選択します。
(アンロード‥‥ロードの逆てきなやつ)

previewに書き換える.png

先頭の方にある<LangVersion>Latest</LangVersion><LangVersion>preview</LangVersion>に書き換えます。

スクリーンショット (56).png
プロジェクトの再読み込みをして、完了です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

C#の基礎をマスターしました。

今日、C#の基礎をマスターしました。
Javaに似ていますね。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[C#] TCPサーバープログラムを作成する

TCPサーバーを C# で構築したかったが、C#フォームアプリケーションから使いやすい形式のものが無かったので、dobon.net さんの下記記事をベースに改編した。
https://dobon.net/vb/dotnet/internet/tcpclientserver.html
スレッドではなくタイマつかってるのでご注意。

ClassTcpServer.cs
namespace TcpServer
{
    // 使い方

    //宣言
    //TcpServer.ClassTcpServer classTcpServer = new TcpServer.ClassTcpServer();

    // 初期化、スタート
    //    classTcpServer.ipaddress = "0.0.0.0";
    //    classTcpServer.port = 49152;
    //    classTcpServer.timerinterval = 100;
    //    classTcpServer.DataReceived += new TcpServer.ClassTcpServer.DataReceivedEventHandler(TcpServer_DataReceived);
    //    classTcpServer.Start();

    // 停止
    //    classTcpServer.Stop();

    // イベントハンドラ
    //private void TcpServer_DataReceived(object sender, TcpServer.DataReceivedEventArgs e)
    //{
    //    //イベントが発生したとき
    //    textBox1.AppendText(e.Message + Environment.NewLine);
    //}


    public class DataReceivedEventArgs : EventArgs
    {
        public string Message;
    }

    class ClassTcpServer
    {
        public string ipaddress { get; set; }
        public int port { get; set; }
        public int timerinterval { get; set; }

        private System.Net.Sockets.TcpListener listener;
        private System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();

        public delegate void DataReceivedEventHandler(object sender, DataReceivedEventArgs e);
        public event DataReceivedEventHandler DataReceived;

        public ClassTcpServer()
        {
        }

        public void Start()
        {
            //TcpListenerオブジェクトを作成する
            listener = new System.Net.Sockets.TcpListener(System.Net.IPAddress.Parse(ipaddress), port);

            //Listenを開始する
            listener.Start();

            // タイマスタート
            timer.Interval = timerinterval;
            timer.Tick += new EventHandler(timer_Tick);
            timer.Start();
        }

        public void Stop()
        {
            // タイマストップ
            timer.Stop();

            if (listener != null)
            {
                //リスナを閉じる
                listener.Stop();
            }
            listener = null;
        }

        private void timer_Tick(object sender, EventArgs e)
        {
            //接続要求が無かったら return
            if (!listener.Pending())
            {
                return;
            }

            //接続要求があったら受け入れる
            System.Net.Sockets.TcpClient client = listener.AcceptTcpClient();

            //NetworkStreamを取得
            System.Net.Sockets.NetworkStream ns = client.GetStream();

            //読み取り、書き込みのタイムアウト
            //デフォルトはInfiniteで、タイムアウトしない
            //(.NET Framework 2.0以上が必要)
            ns.ReadTimeout = 10000;
            ns.WriteTimeout = 10000;

            //クライアントから送られたデータを受信する
            System.Text.Encoding enc = System.Text.Encoding.UTF8;
            bool disconnected = false;
            System.IO.MemoryStream ms = new System.IO.MemoryStream();
            byte[] resBytes = new byte[256];
            int resSize = 0;
            do
            {
                //データの一部を受信する
                resSize = ns.Read(resBytes, 0, resBytes.Length);
                //Readが0を返した時はクライアントが切断したと判断
                if (resSize == 0)
                {
                    disconnected = true;
                    break;
                }
                //受信したデータを蓄積する
                ms.Write(resBytes, 0, resSize);
                //まだ読み取れるデータがあるか、データの最後が\nでない時は、
                // 受信を続ける
            } while (ns.DataAvailable || resBytes[resSize - 1] != '\n');
            //受信したデータを文字列に変換
            string resMsg = enc.GetString(ms.GetBuffer(), 0, (int)ms.Length);
            ms.Close();
            //末尾の\nを削除
            resMsg = resMsg.TrimEnd('\n');

            // イベント発生して呼び出し元にデータを返す
            DataReceivedEventArgs ee = new DataReceivedEventArgs();
            ee.Message = resMsg;
            DataReceived(this, ee);

            if (!disconnected)
            {
                //クライアントにデータを送信する
                //クライアントに送信する文字列を作成
                string sendMsg = resMsg.Length.ToString();
                //文字列をByte型配列に変換
                byte[] sendBytes = enc.GetBytes(sendMsg + '\n');
                //データを送信する
                ns.Write(sendBytes, 0, sendBytes.Length);
            }

            //閉じる
            ns.Close();
            client.Close();
        }
    }
}

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ubuntu上でC言語やC#を各種エディタで書いてみる

Linuxは、狭義にはLinuxカーネル、広義にはそれをカーネルとして用いたオペレーティングシステムを指します。LinuxはUnix系オペレーティングシステム (OS) の1つと言えます。
UbuntuはLinuxディストリビューションの1つです。初心者からベテランまで、幅広く利用されています。

本稿では、C言語やC#のプログラムを各種エディタを用いて作成します。

参考URL

VirtualBox上にUbuntu 20.04をインストールする方法は、以下のリンクが参考になると思います。
プログラマーのためのUbuntu

C言語のコンパイル環境を構築しよう

端末を起動し、以下を実行します。

sudo apt update
sudo apt install build-essential

geditでC言語を編集してみる

geditはUbuntu標準のエディタで、初心者向けと言えます。ディスクトップ最上段の「アクティビティ」をクリックし、「ged」と入力してgeditを起動します。

無題のドキュメント-1-gedit_004.png

まず、geditの下の「なし」をクリックし、メニューから「C」を選択します。そして次のコードを入力します。

sample01.c
#include <stdlib.h>
int main()
{
  system("/bin/cat /etc/lsb-release");
}

すると、エディタ上のコードはシンタックスハイライトされて表示されます。
次に、gedit上部の保存ボタンをクリックし、「sample01.c」として保存します。そして次のコマンドでコンパイルし、実行してみます。

gcc -o sample01 sample01.c
./sample01

下記のように、Ubuntuのバージョン情報が表示されれば成功です。

実行結果
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=20.04
DISTRIB_CODENAME=focal
DISTRIB_DESCRIPTION=”Ubuntu 20.04 LTS”

C#の編集と実行に挑戦してみる

まず、C#をインストールします。

C#のインストール
sudo apt install mono-devel

今度はnanoというエディタを使ってみます。nanoはGUIを持たない、CUIベースのエディタです。リモートログインして作業するなど、GUIが使用できない環境でも使用できる利点があります。

nanoの起動
nano sample02.cs

以下のコードを入力します。

sample02.cs
using System;
using System.IO;
using System.Text;
class FileRead1 {
  static void Main() {
    StreamReader sr = new StreamReader(
                            "/etc/lsb-release");
    string text = sr.ReadToEnd();
    sr.Close();
    Console.Write(text);
  }
}

Ctrl+Oで”sample02.cs”という名称でファイルに書き込みます。次にCtrl+Xで終了します。nanoを終了したら、コンパイルします。

C#のコンパイル
mcs sample02.cs

コンパイルが完了すると、”sample02.exe”というファイルが生成されています。”sample02.exe”を実行してみてください。

sample02の実行
./sample02.exe

先ほどのC言語のプログラムと同じ、Ubuntuのバージョン情報が出力されます。

Visual Studio Codeのインストール

最後に、人気のVisual Studio Codeのインストール方法を紹介します。Ubuntu20.04ではsnapを用いてインストールできます。

VScodeのインストール
sudo snap install --classic code
code

Welcome-Visual-Studio-Code_005.png

さいごに

Windows10の環境であれば、WSL(Windows Subusystem for Linux)のUbuntuから実行するのが手っ取り早いでしょう。
WSLのUbuntuを構築する方法は、よければ以下のリンクを参考にしてみてください。

LinuxとWindowsの欲張りな環境を手にする

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【C#⇔C++/CLI】ファイルまたはアセンブリ、またはその依存関係の1つが読めませんでした。【トラブルシューティング】

概要

Windows専用のアプリケーションなんて今更・・・という昨今ですが、

未だに.NET Frameworkや.NET Coreで、C++のコードとC#のコードをまとめて使うときにC++/CLIというMicrosoftが開発した中間言語を使って、ネイティブコードを共存させたいという需要が狭い世界で存在します。

C++/CLIは、現状C++用のラッパーとしてDLLとして作成する場合での運用でのみ、Microsoftからも推奨されています。

そして、.NET FrameworkのC++/CLIの設定を誤ると、表題のエラーを見かけるようになります。

この狭い世界で何度か開発することがあったので、C++/CLI導入時のチェックリストみたいなのを用意しておこうと思います。

Windows Forms, WPF, UWPの場合

C++/CLIで結合されているオブジェクトを参照すると、こんな感じのエラーが出てきます。

image.png

チェックするべき項目

実行ファイル側が"Any CPU"になっていないこと

実行されるDLLと実行ファイル側が"x86/Win32"または"x64"に統一されていること

image.png

基本的に、C++/CLIで作成されたDLLは、32bitで使用するか64bitで使用するかを指定する必要があります。
両方のCPUで使えるような器用な仕様にはなっていません。
従って、上のように"Any CPU"という設定が混在している場合は、"x86/Win32"または"x64"に設定を統一しましょう。

image.png

実行予定のDLLが、全く同じディレクトリに含まれていること

① C++/CLI以外に、C++ネイティブDLLが混在する場合は、ビルド時に自動的に実行ファイルのディレクトリ下に保存してくれません。
その場合は、ビルドイベントを使って、dllファイル、pdbファイルをコピーするようにしましょう。
(pdbファイルを入れ忘れると、ネイティブコードのデバッグが出来なくなるので注意すること。)

② もし依存関係が分からない場合は、Dependenciesをダウンロードして調べると、一目で理解できます。

ASP .NETの場合

ローカルサーバを立てた場合のデバッガの挙動
大体こんな感じの画面になります。

image.png

チェックするべき項目

基本的には、上記のケースと同じですが、これ以外に下記の内容も確認しましょう。

IIS Expressが32ビット版、64ビット版に統一されているかを確認する

ツール>オプション>プロジェクトおよびソリューションを参照

64bitのC++/CLIのDLLを使用する場合は、Webサイトおよびプロジェクト用IIS Expressの64ビットバージョンを使用するにチェックを入れます。

image.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Html.ActionLinkを使うとhrefに「?Length=4」がついてしまう

起こったこと

Viewで@Html.ActionLinkを使ってaタグを作成すると、hrefに「?Length=4」がついてしまう。

CSHTML
@Html.ActionLink("About", "About", "Home", new { @class = "btn btn-primary" })

原因

コントローラーを直で書いているのが原因みたい。

string routeValuesのオブジェクト「Home」を取得します。MVCはこれをパブリックプロパティを検索してルート値に変換します。stringオブジェクトの場合、唯一のパブリックプロパティはLengthであり、Lengthパラメータでルートが定義されないため、プロパティ名と値がクエリ文字列パラメータとして追加されます。

対処

string controllerNameにべた書きせずにstring routeValuesに設定する。

CSHTML
@Html.ActionLink("About", "About", new { controller = "Home" }, new { @class = "btn btn-primary" })
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む