🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

メモリリーク

メモリリークは、プログラムファイルがメモリの解放に失敗した時に起こります。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

3回答

8725閲覧

Staticなメソッドとシングルトンのどちらを使えばいいか?

Enoki_Nameko

総合スコア8

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

メモリリーク

メモリリークは、プログラムファイルがメモリの解放に失敗した時に起こります。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

1クリップ

投稿2019/11/30 18:05

Unityにて開発をしています。

私はWolfRPGEditorからゲーム開発に入ったので、できるだけ上から下に流すようなプログラムがしたいと思っており、
すべてのクラスにコルーチンを用意して、それをシーンに一つだけ存在するシーンマネージャーで呼び出していくような形にしようと思ってるのですが、

その際に呼び出す別クラスのメソッドをシングルトンでインスタンスを生成して呼び出すべきか、

public class Test { public static IEnumerator Main() { //ここに処理 yield break; } }

上のように書いて、これをyield return Test.Main();のように呼び出して使ってもいいものかで悩んでいます。

なぜ悩んでいるかと言うと、static変数はプログラム実行時にメモリ領域を食べるというのを読んだからです。
ただ、staticなメソッドについての詳しい挙動が書かれてるものがなかったので、
staticなメソッドがプログラム実行時にメモリ領域をどのように確保するのかも知りたいです。

メソッドの中のローカル変数ごとメモリを食うのでしょうか?
それともメソッドの参照みたいなのがメモリに渡されてメモリ領域一個で済むみたいな感じなのでしょうか?

あとやはりstaticなもの(変数とかメソッドとかクラスとか)が多いと重くなったりするんでしょうか?
食べるは食べるけど、1000個くらいのstaticメソッド程度ではあまり影響がなかったりするんでしょうか?

初の質問で不備などあるかもしれませんが、よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

otn

2019/12/01 00:26

> static変数はプログラム実行時にメモリ領域を食べる 意味不明の記述です。おそらく誤読です。どこに書いてありましたか?
Enoki_Nameko

2019/12/01 00:34

https://qiita.com/Nekonecode/items/19f3a261a8391853ddec ここです。static変数がメモリ領域を使用しないのであればいいのですが、しない場合はどこからでも呼び出すことができなくなりそうなので、記事は合ってると思うのですが、違うんでしょうか?
otn

2019/12/01 00:44

> ここです。 そのページに「食べる」という記述が見つかりません。 また、このページはPHPの説明ですが、認識合ってますか? > static変数がメモリ領域を使用しないのであればいいのですが どんな変数であれ、変数はメモリを使うに決まっています。 メモリ領域に名前を付けたのが変数です。
Enoki_Nameko

2019/12/01 00:47

下記の文章ですね。 いままで、クラスに定義した変数はnewすることでメモリが確保されていました。 逆に言えば newしない限り、その変数はメモリ上に存在しないので当然アクセスできません。 さらにメモリのどこに確保されるのかも、newしてみないとわかりません。 newが、メモリを確保して、さらに「確保した場所はここだよ!」 と教えてくれて初めてデータにアクセスすることができます。 それに対して、staticがついた変数は 基本的にプログラムが実行されるタイミングで あらかじめメモリが確保されています。 一度確保したら、プログラムが終了されるまでずっと確保されたままです。 場所も固定されています。
otn

2019/12/01 00:52

「食べる」の意味は?? 上記に書いた通り、変数であるかぎりメモリは必ず使います。
Enoki_Nameko

2019/12/01 00:55

確保するという意味です。
otn

2019/12/01 01:16

staticな変数だけがメモリを確保して、newしたオブジェクトはメモリを確保しないと思ったのですか? であれば、誤読です。
Enoki_Nameko

2019/12/01 01:18

newしたオブジェクトがメモリを確保することは知っています。
otn

2019/12/01 01:23

では、 > なぜ悩んでいるかと言うと、static変数はプログラム実行時にメモリ領域を食べるというのを読んだからです。 は、何を悩んでいるのでしょう?
Zuishin

2019/12/01 03:53

言語が違うので全く参考にならないし、PHP の記事としてもお粗末な部類に入ると思います。 > 細かいことを突っ込むと、正確ではないという部分もあるかと思いますが ご容赦ください。
guest

回答3

0

ベストアンサー

こんにちは。

static変数はプログラム実行時にメモリ領域を食べるというのを読んだからです。

普通の変数もstatic変数も、変数としての領域と変数を管理する領域を確保します。
むしろ、普通の変数の方がメモリ消費はわずかに多い筈です。

ただ、staticなメソッドについての詳しい挙動が書かれてるものがなかったので、
staticなメソッドがプログラム実行時にメモリ領域をどのように確保するのかも知りたいです。

非staticメソッドもstaticメソッドも実行時のメモリ領域の確保方法にほぼ差はありません。
これらの差は、原理的に自身のオブジェクトへのポインタ=thisを(隠れ)引数として受け取るか否かだけの差です。

メソッドの中のローカル変数ごとメモリを食うのでしょうか?

それともメソッドの参照みたいなのがメモリに渡されてメモリ領域一個で済むみたいな感じなのでしょうか?

メソッド=プログラムです。1つのメソッドはstaticでも非staticでも、それ自身が記録される領域は1セットだけです。普通の(=非static)メソッドがオブジェクトの数だけそのメソッドのコード(プログラム)までコピーされていそうな気がするかも知れませんが、そんなことはありません。メソッドのコードは1セットだけです。

また、メソッドのローカル変数は当該メソッド実行中だけ確保されます。
当該メソッドが実行されていない時、そのローカル変数はメモリを消費しません。(メモリ上に確保されていません。)
再帰呼び出しや複数のスレッドからの呼び出し等で同時に同じメソッドが多重に実行されている場合、多重に実行されている数だけローカル変数も確保されます。
これは通常のメソッド、staticメソッドともに同じです。

あとやはりstaticなもの(変数とかメソッドとかクラスとか)が多いと重くなったりするんでしょうか?

食べるは食べるけど、1000個くらいのstaticメソッド程度ではあまり影響がなかったりするんでしょうか?

逆です。「重さ」で言えば、非staticな変数やメソッドやクラスの方がstaticなそれらより「重い」です。staticなそれらは「静的」です。それはプログラム実行中に変更されないという意味です。つまり、その変更のために資源(メモリやCPU)を消費しないということです。
でもその差は誤差範囲ですから気にする必要はありません。この差が気になるようなプロジェクトはC#ではなくC++を使うべきですし、もしかするとC言語やアセンブラを使うべきプロジェクトかも知れません。

投稿2019/12/01 03:41

編集2019/12/01 04:13
Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Enoki_Nameko

2019/12/01 04:14

最後の重いというのは表現が的確ではなかったです。より多くメモリを消費するのでしょうか?と言いたかったです。 処理速度的なもので言うならstaticの方が軽いというのがわかって嬉しいです。 あと、「staticでない変数は、インスタンスを生成しない場合にはメモリ領域が確保されない」という認識で合っているでしょうか?合っているのであれば、static変数やメソッドが多いとメモリを消費しすぎるのではないか?という心配があります。 この場合もメモリ消費量は気にするほどではないのでしょうか?それともやはりstaticなメソッドはやめて、インスタンスを生成していったほうがメモリ消費的にはいいのでしょうか? 非staticなメソッドはインスタンスを生成しない場合、ただのコードの羅列としてメモリ領域が確保されていない状態で、staticなメソッドは即時アクセスが可能でメモリ領域が確保されてしまっているのでしょうか? 質問が多くて申し訳ないのですが、よろしくお願いいたします。
Chironian

2019/12/01 04:54 編集

> あと、「staticでない変数は、インスタンスを生成しない場合にはメモリ領域が確保されない」という認識で合っているでしょうか? 合ってます。 > 合っているのであれば、static変数やメソッドが多いとメモリを消費しすぎるのではないか?という心配があります。 それが気になるのでしたら、そのように対処すれば良いだけです。 一般にメモリを多く使うように設計したらメモリ消費が増えます。ごくごく当たり前の話です。staticだろうが非staticだろうが同じことです。 実行時に必要かどうか分からない巨大なメモリをstaticに確保するのは愚かですね。 実行時に必要かどうか分からなくても微細なメモリをstaticに確保することでプログラムの構造を単純化できるなら、プログラムの信頼性確保のために微細なメモリを消費することは正当化出来る場合が多いです。(C#とはそもそもそのような思想に基づいた言語です。) C#を使うようなプログラムにとって1000個程度のint型変数は「微細」に分類しても問題ないです。 実領域はたかだか4KBytesですから。 > 非staticなメソッドはインスタンスを生成しない場合、ただのコードの羅列としてメモリ領域が確保されていない状態で、staticなメソッドは即時アクセスが可能でメモリ領域が確保されてしまっているのでしょうか? 非staticメソッドもstaticメソッドもメモリ消費については事実上同じです。 回答にて「コードはどちらも1セットのみ」、「ローカル変数はどちらも実行時のみ確保される」と明確に提示したと思うのですが。
Zuishin

2019/12/01 04:57 編集

static の方が軽いというのは理論的なもので、実際には差は出ないと思います。 > でもその差は誤差範囲ですから気にする必要はありません。 短距離走をするのに服を着るか全裸かくらいの違いではないでしょうか。
Enoki_Nameko

2019/12/01 06:15

回答ありがとうございます。 >非staticメソッドもstaticメソッドもメモリ消費については事実上同じです。 回答にて「コードはどちらも1セットのみ」、「ローカル変数はどちらも実行時のみ確保される」と明確に提示したと思うのですが。 これについては >メソッド=プログラムです。1つのメソッドはstaticでも非staticでも、それ自身が記録される領域は1セットだけです。 >また、メソッドのローカル変数は当該メソッド実行中だけ確保されます。 と答えていただいたので、ローカル変数は実行時のみ確保されるとわかったのですが、インスタンスを生成していない状態でもメソッドの情報がメモリに確保されてしまうのかが気になった次第です。 メソッドのメモリ消費量もint型変数と同程度なのでしょうか?そうなのであれば、メソッドがstaticだろうが気にするほどのことではないということも理解できます。 あと色々教えていただいて思ったのですが、全てstaticでプログラムしてしまうのはダメなんでしょうか?もちろんStartメソッドなどを使おうとするとstaticではダメだった気がするので、そのあたりは臨機応変に対応させないといけないでしょうけど、現状static変数も大したメモリ消費量にならないのであれば、staticの方が呼び出すときにインスタンスを生成する手間も処理もなくて楽な気がします。 Singletonも中でアップデート関数などを呼ばない限りは、ただのstaticなクラスでもいいんでしょうか? オブジェクトごとに変数を持たせたい場合とかはstaticじゃダメなのはわかるんですが、共通の変数でいい場合はstaticの方が何かと楽な気がしているんですが、この認識は間違っているでしょうか? よろしくお願いいたします。
Chironian

2019/12/01 07:41 編集

> インスタンスを生成していない状態でもメソッドの情報がメモリに確保されてしまうのかが気になった次第です。 回答に記載したように通常のメソッドもオブジェクトの数に関わりなく1セットだけメモリに記録されます。 > メソッドのメモリ消費量もint型変数と同程度なのでしょうか?そうなのであれば、メソッドがstaticだろうが気にするほどのことではないということも理解できます。 「メソッドのメモリ消費量」とは何を指していますか? C#の場合、メソッドのコードとローカル変数の2つだけと思います。もし、他に何か想定されているのでしたら、それを明示下さい。 > 全てstaticでプログラムしてしまうのはダメなんでしょうか? 性能だけをギチギチに追求する場合は理論上考えられないこともない方針ですが、それをC#で行うのは「愚か」以外の何物でもありません。オブジェクト指向プログラミングの利点を全て投げ捨ててでも性能を追求するのであれば、C言語で書いた方が良いと思います。 > オブジェクトごとに変数を持たせたい場合とかはstaticじゃダメなのはわかるんですが、共通の変数でいい場合はstaticの方が何かと楽な気がしているんですが、この認識は間違っているでしょうか? 稀に正しい場合がありますが、多くの場合で間違っています。 基本はオブジェクト指向プログラミングするべきです。例外的にそれから外れた方が好ましいケースもあります。 例えば、C#はグローバル関数とグローバル変数をサポートしていないため、グローバル関数やグローバル変数で実装するのが望ましいケースではstaticメソッドやstatic変数で代用することがあります。そのようなケースは正しいです。 しかし、オブジェクト指向プログラミングの利点を理解していない内は避けた方が、より速く優秀なプログラマになれるだろうと思います。(学習においてステップ・バイ・ステップは有用です。)
Enoki_Nameko

2019/12/01 09:45

回答ありがとうございます >「メソッドのメモリ消費量」とは何を指していますか? C#の場合、メソッドのコードとローカル変数の2つだけと思います。もし、他に何か想定されているのでしたら、それを明示下さい。 わかりづらくてすみません。 int型変数の場合は、クラスをインスタンスした場合、もしくはそのint型変数がstaticな場合、メモリ領域を1枠使うことは理解したのですが、メソッドはインスタンスしなくてもメモリ領域に登録されているのかどうかが私の理解力不足で文章からちょっと読み取れなかったので確実な情報がほしいと思い、再度質問させていただいた次第です。すみません。 >オブジェクト指向プログラミングの利点を全て投げ捨ててでも性能を追求するのであれば、C言語で書いた方が良いと思います。 オブジェクト指向って部品ごとなどに分けてプログラムすることですよね?それをしないわけではなく、単純にstaticで記述すればメソッドの呼び出しが楽だなあと思ったんです。
Chironian

2019/12/01 10:41

> 単純にstaticで記述すればメソッドの呼び出しが楽だなあと思ったんです。 アルゴリズムとデータ構造がセットになることは結構多いです。そして、それらを「オブジェクト」として捉えることで複数のオブジェクトが互いに関わり合って機能するプログラムとして設計・コーディングできます。 その結果はデバッグしやすく改造が容易なプログラムとなることが多いです。逆にデバッグしやすく改造が容易なプログラムを書こうと努力していると自然にオブジェクト指向的になることが多いと言っても良いかも知れません。 もし、「staticの方がデバッグやメンテナンスしやすい」と感じているのであれば、自力で創意工夫しつつオブジェクト指向プログラミングの境地に達するのを待つのも手かも知れません。 もし、「デバッグやメンテナンスを考慮した設計は面倒なので、staticで楽したい」と感じているのであれば、それはスパゲティプログラムへ至る道ですから、楽しない方がより優秀なプログラマになれるだろうと思います。
Enoki_Nameko

2019/12/01 12:01

変数→インスタンス生成時に変数への参照と値をメモリに保存 staticな変数→プログラム実行時に変数への参照と値をメモリに保存 メソッド→インスタンス生成時にメソッドへの参照をメモリに保存 staticなメソッド→プログラム実行時にメソッドへの参照をメモリに保存 ということでいいんでしょうか? あとstaticにすることによってスパゲティプログラムになることが想像できないのですが、どのような場合にスパゲティになるのでしょうか?なんならstaticにしている方が呼び出しにかかるコード量が少ないのでコードが読みやすい気さえします。 あとstaticメソッドを使わないのであれば、複数存在してはいけないクラスの場合はシングルトンで実装した方がいいということでしょうか? ただシングルトンってUpdateなどが動けるだけで、それらを使わないのであれば、staticな変数にメソッドへの参照?をどっちにせよ渡すのでやってることは一緒なんじゃないかと思ったのですが、これはどうなんでしょう? ただシングルトンならメモリの解放を意図的に行うことができるのは強みだなあとは思います。でもそれも大した差じゃない(大規模な開発になってくると違いそうだけど)のであれば、staticでもいいのかなあと。
Chironian

2019/12/01 15:27

> メソッド→インスタンス生成時にメソッドへの参照をメモリに保存 > staticなメソッド→プログラム実行時にメソッドへの参照をメモリに保存 決定的に間違っています。メソッドはCPUへの命令の集まりです。それらの命令群はプログラムの起動時にメモリへロードされます。 > あとstaticにすることによってスパゲティプログラムになることが想像できないのですが、どのような場合にスパゲティになるのでしょうか? static変数はどこからでもアクセスできます。Enoki_Namekoさんが想定していないところからアクセスするようなコードを書くプログラマがいるかも知れません。Enoki_Namekoさん自身も不適切な場所から安易にアクセスするかも知れません。static関数も同様です。どこからでも呼べますので、不適切な場所から呼び出すかも知れません。こうしてスパゲティ・プログラム(混乱した無闇に複雑なプログラム)が出来上がって行きます。 プログラムが大きくなってくると、そのような「おバカ」なことをやるのが人間なのです。人はミスする動物なのですよ。Enoki_Namekoさんがそのようなことを経験したことがなくても、過去の多くのプログラマーが実際に経験してきたのです。そして、そのような問題を回避しつつ、生産性を落とさない優れた手法の一つがオブジェクト指向プログラミングです。 > あとstaticメソッドを使わないのであれば、複数存在してはいけないクラスの場合はシングルトンで実装した方がいいということでしょうか? スパゲティ化回避のため、static変数を使わない代わりにシングルトンを使うというのは決定的に無意味です。 小規模プログラムの場合、構成要素間は密結合した方が生産性は上がりますので、おっしゃるようにstatic変数を多用すると開発効率は高いです。 しかし、数千行を越えるようなプログラムになってくると、全ての構成要素が密結合しているとデバッグで地獄を見ます。ある程度の粒度でモジュール分割し、モジュール内は密結合、モジュール間は疎結合とするのが鉄則です。 この辺りを想像できないようでしたら、この分野の議論のために必要な経験を積まれていません。これ以上の議論は無意味となります。
Enoki_Nameko

2019/12/01 16:18

>メソッドはCPUへの命令の集まりです。それらの命令群はプログラムの起動時にメモリへロードされます。 ということは極端な話、絶対にすることはないでしょうけど、メソッドが1つしかない尋常じゃないほど長いコードを書いたほうがメモリへの負担は少ないということでしょうか?それとも1個だろうが1兆個だろうが書いたコードの行数分負担が増えると言った感じなのでしょうか? >static変数はどこからでもアクセスできます。 これは、staticの場合はオブジェクトを生成せずにアクセスすると、アクセスしようとしたときに必ず同じ変数を触る関係で、変な値を代入されたりして危ない。ということでしょうか?たしかにプロジェクトの規模が大きくなると人為的ミスが起きやすいので危なさそうです。 このあたりは個人開発の場合はそこまで気にすることでもないのでしょうか?もちろん、今後のことを考えるときちんとしたほうがいいんでしょうが・・・。
Chironian

2019/12/01 16:53

> それとも1個だろうが1兆個だろうが書いたコードの行数分負担が増えると言った感じなのでしょうか? 考え方としては こちらが正しいです。 > これは、staticの場合はオブジェクトを生成せずにアクセスすると、アクセスしようとしたときに必ず同じ変数を触る関係で、変な値を代入されたりして危ない。ということでしょうか? その通りです!! > このあたりは個人開発の場合はそこまで気にすることでもないのでしょうか? 100行くらいの小さな「スクリプト」を書くようなケースでは、ほぼ気にしないで良いと思います。 数千行を越えるようなプログラムを書く時は気にした方が開発期間を短縮できると思います。
Enoki_Nameko

2019/12/01 21:34

なるほど!なんとなくわかってきました! 私の場合はおそらく前者のスクリプトの集合体みたいな感じでゲーム制作をするので、もしかしたらほぼ気にしなくていいかもしれないです。というかもしかしたら一人で開発するので、非staticよりstaticなメソッドの方が同じ変数を触りにいく関係上、逆に変更の幅が効くことがあるかもしれません。もちろんそうじゃない場合もあるでしょうが。 なんとなくすべきことが見えてきた気がします。色々とありがとうございました!
Zuishin

2019/12/01 21:55

誤解の上に誤解を積み重ねているだけにしか見えない。
guest

0

Staticなメソッドとシングルトンのどちらを使えばいいか?

使用するメモリ量という観点だけ心配しているのであれば、同じか、誤差の範囲です。
Staticメソッドより、シングルトンオブジェクト+インスタンスメソッドの方が、オブジェクトの分だけごくわずかに多いと思いますが。

投稿2019/12/01 01:21

otn

総合スコア85893

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

static変数はプログラム実行時にメモリ領域を食べる

そもそもそれが間違ってます

投稿2019/12/01 00:08

y_waiwai

総合スコア88040

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問