沢山の関数があるなかで絶対に先に呼ばれる関数を設置したいのですが、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が呼び出された後に各関数内処理が走ります。
このような形で書いてもいいんですが、見栄えが悪くて気持ちが悪いです。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答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総合スコア13512
0
現在の愚直なやり方が無難とは思いますがいくつか思ったことを書いておきます。
- 純粋なC#のプログラミングに関する質問でしょうか?
- Unity等に関する方法論でしたら別の案があるかもしれません。
- staticである必要はありますか?
- staticなクラス内での処理に対して、別な関数を複数から呼ぶのには違和感を感じます
- スレッドセーフとはいかないまでも複数から呼び出された場合に問題ない処理でしょうか?
もう少し具体的にやりたいことを書かれると別な案があるかもしれません。
なお、黒魔術的な方法としては、RealProxy とかもなくはないですが…
投稿2018/06/25 23:29
総合スコア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
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2018/06/26 01:59
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総合スコア4103
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
総合スコア5938
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
本当に最初に関数を一つ呼び出すだけであれば、その書き方が一番良いのではないかと思います。
(後処理も何か固定的に呼びたいとなると、もう少し別の方法も提案できるかもしれませんが。)
投稿2018/06/26 00:50
総合スコア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総合スコア4447
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。