質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.50%
C#

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

Q&A

8回答

3514閲覧

C# 必ず呼ばれる関数を同クラス内に持ちたい

Hit01

総合スコア5

C#

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

1グッド

1クリップ

投稿2018/06/25 18:58

沢山の関数があるなかで絶対に先に呼ばれる関数を設置したいのですが、Staticなクラス内で定義する良い方法は有りませんか?

例として以下のようなクラスが有るとします。

C#

1public static class Sample{ 2 3 public static void A(){ 4 SET(); 5 ... 6 } 7 8 public static void B(){ 9 SET(); 10 ... 11 } 12 13 public static void C(){ 14 SET(); 15 ... 16 } 17 18 public static void SET(){ 19 20 } 21 22}

このクラスではFunction A B C内で必ずFuncSETが呼び出された後に各関数内処理が走ります。

このような形で書いてもいいんですが、見栄えが悪くて気持ちが悪いです。

oriduru👍を押しています

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

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

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

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

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

guest

回答8

0

そのままでもいい気はするが、

SET()のあとに必ずなにかするというのであれば
SETを改造して

C#

1private static void SetThen(Action action){ 2 SETの内容 3 action(); 4}

を用意して

C#

1public void A(){ 2 SetThen(()=>{処理}); 3} 4public void B(){ 5 SetThen(()=>{処理}); 6} 7public void C(){ 8 SetThen(()=>{処理}); 9} 10

仮にSET後の処理の種類がどんどん追加されるならSetThen()自体を公開してもいいかと。

投稿2018/06/26 02:40

編集2018/06/26 02:44
ozwk

総合スコア13512

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

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

0

現在の愚直なやり方が無難とは思いますがいくつか思ったことを書いておきます。

  • 純粋なC#のプログラミングに関する質問でしょうか?
    • Unity等に関する方法論でしたら別の案があるかもしれません。
  • staticである必要はありますか?
    • staticなクラス内での処理に対して、別な関数を複数から呼ぶのには違和感を感じます
    • スレッドセーフとはいかないまでも複数から呼び出された場合に問題ない処理でしょうか?

もう少し具体的にやりたいことを書かれると別な案があるかもしれません。

なお、黒魔術的な方法としては、RealProxy とかもなくはないですが…

投稿2018/06/25 23:29

mituha

総合スコア385

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

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

0

全体的なやりたいことが不明なので外れかもしれませんが、コンストラクターでなんとかできないですか?

【追伸】

訂正:YAmaGNZ さんのご指摘の通り、以下の例はインスタンスクラスで質問者さんの言われる「Staticなクラス内」ではないです。すみません。【追伸2】に「Staticなクラス内」の例を書いておきます。

言葉だけではピンとこないと思いますので、Windows Forms アプリで使われているコード例をアップしておきます。(質問者さんのケースではこのようにできるかどうかは分かりませんが)

Program.cs の Main メソッドがエントリーポイントで、そこで Form4() というコンストラクタを使って Form を初期化すると、Form4.cs に定義されている Form4() コンストラクタで InitializeComponent() メソッドが起動され、Form 上に配置されたコントロール類が初期化されます。

この InitializeComponent() メソッドが質問者さんの言う「必ず呼ばれる関数」に該当します。

Program.cs

using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; namespace WindowsFormsApplication1 { static class Program { /// <summary> /// アプリケーションのメイン エントリ ポイントです。 /// </summary> [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form4()); } } }

Form4.cs

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace WindowsFormsApplication1 { public partial class Form4 : Form { public Form4() { InitializeComponent(); } } }

Form4.Designer.cs

namespace WindowsFormsApplication1 { partial class Form4 { /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> /// Clean up any resources being used. /// </summary> /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.pictureBox1 = new System.Windows.Forms.PictureBox(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); this.SuspendLayout(); // // pictureBox1 // this.pictureBox1.Location = new System.Drawing.Point(13, 13); this.pictureBox1.Name = "pictureBox1"; this.pictureBox1.Size = new System.Drawing.Size(100, 50); this.pictureBox1.TabIndex = 0; this.pictureBox1.TabStop = false; // // Form4 // this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 15F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(262, 120); this.Controls.Add(this.pictureBox1); this.Name = "Form4"; this.Text = "Form4"; ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); this.ResumeLayout(false); } #endregion private System.Windows.Forms.PictureBox pictureBox1; } }

【追伸2】

static class でのコンストラクタの定義の記事です。記事の中に MSDN へのリンクも張ってありますので見てください。

C# static class constructor
https://stackoverflow.com/questions/6721832/c-sharp-static-class-constructor

具体例も書いておきます。

namespace ConsoleApplication4 { static class YourClass { static string s = null; static YourClass() { // perform initialization here s = "test string"; } public static string Method1() { return s; } } class Program { static void Main(string[] args) { var x = YourClass.Method1(); } } }

投稿2018/06/25 23:00

編集2018/06/26 02:17
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

YAmaGNZ

2018/06/26 01:38

質問者が「staticなクラスで」と質問されているのに、何故インスタンスを作成しての例なのでしょう?
退会済みユーザー

退会済みユーザー

2018/06/26 01:59

そうですね。訂正しておきます。ご指摘ありがとうございました。
guest

0

こんにちは。
目的が不明なので外してるかもしれませんが、staticコンストラクタでは目的を達成できませんか?

csharp

1static Sample(){ 2 SET(); 3} 4

追記

コードが別物ですけど、テンプレートメソッドパターン……とか。

csharp

1 public abstract class Sample 2 { 3 public void Run() 4 { 5 this.SET(); 6 this.Action(); 7 } 8 9 private void SET() 10 { } 11 12 protected abstract void Action(); 13 } 14 15 public class A : Sample 16 { 17 protected override void Action() 18 { 19 // A... 20 } 21 } 22 23 public class B : Sample 24 { 25 protected override void Action() 26 { 27 // B... 28 } 29 } 30 31 public class C : Sample 32 { ... }

投稿2018/06/25 22:54

編集2018/06/26 22:57
tamoto

総合スコア4103

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

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

len_souko

2018/06/26 13:04

それだとSETは一回しか呼ばれないはずですが、質問者のソースを見るとメソッドを呼ぶたびに毎回実行するように見えますが・・・ もっとも質問者がどういう状況で書いているのかわからないので提示されているソースが誤りだったら回答も明後日の方向にしか進まないんですけどね
tamoto

2018/06/26 22:48

なるほど、どのメソッドでも実行する度に特定の初期化処理を行いたいってことでしたか。 それは、まずstaticにしてるのが間違いですかね……。
guest

0

C#ではそういうことを直接的に行うような機能はないので、何らかの仕組みを考える必要がありますが、staticクラスだと、できることが限られるので難しいですね。

ぱっと思いつくものとしては、staticメソッドを実行するstaticメソッドを作ることでしょうか。

C#

1public static class Sample 2{ 3 public static void Invoke(Action iAction) 4 { 5 SET(); 6 iAction(); 7 } 8 : 9 : 10} 11 12static void Main(string[] args) 13{ 14 Sample.Invoke(Sample.A); 15}

これもちょっと気持ち悪いと思われるかもしれませんが。

投稿2018/06/26 04:19

catsforepaw

総合スコア5938

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

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

0

C#にはそういう機能はないので、その見栄えの悪い方法でするしかないかと

#なにをしたいんだろう

投稿2018/06/25 21:59

y_waiwai

総合スコア87719

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

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

0

本当に最初に関数を一つ呼び出すだけであれば、その書き方が一番良いのではないかと思います。
(後処理も何か固定的に呼びたいとなると、もう少し別の方法も提案できるかもしれませんが。)

投稿2018/06/26 00:50

takabosoft

総合スコア8356

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

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

0

やりたいことは「アスペクト指向」的なことでしょうか。
(アスペクト指向が何のことかわからない場合は申し訳ないですが調べてください)

まずは、以下の記事をご覧になってそのまま実装してみてください。
C#でアスペクト指向
SampleClassに実装されたメソッドを実行すると、処理の最初と最後にログが出力されます。

ただ、これはSampleClassがインスタンス化されている必要があり、staticで同じことをする方法は思いつきませんでした。
そこでシングルトンパターンにしてインスタンスをstaticに持てば・・・それっぽいかな?

C#

1public class Program 2{ 3 static void Main() 4 { 5 SampleClass.GetInstance().SampleMethod("テスト実行"); 6 Console.ReadLine(); 7 } 8} 9 10//実行対象クラス 11[MyAspect] 12public class SampleClass : ContextBoundObject 13{ 14 private static SampleClass _instance = new SampleClass(); 15 16 public static SampleClass GetInstance() 17 { 18 return _instance; 19 } 20 21 private SampleClass() 22 { 23 24 } 25 26 public string SampleMethod(string str) 27 { 28 Console.WriteLine(str); 29 return null; 30 } 31}

※MainとSampleClass以外はリンク先の記事と同一です

この方法はSampleClassのどのメソッドを実行してもログが出力されます。
SET()を実行したいメソッドとしたくないメソッドが混じっているなら、素直にSET()書いたほうがスッキリするかと思います。

追記

MyProxyのinvokeメソッドにて、call.MethodNameでメソッド名が取れます。
メソッド名にどんな文字が含まれているかで事前処理内容の分岐ができたりします。

投稿2018/08/08 13:52

編集2018/08/08 13:58
hope_mucci

総合スコア4447

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問