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

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

ただいまの
回答率

90.50%

  • C#

    7119questions

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

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

受付中

回答 8

投稿

  • 評価
  • クリップ 1
  • VIEW 751

Hit01

score 1

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

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

public static class Sample{

     public static void A(){
          SET();
          ...
     }

     public static void B(){
          SET();
          ...
     }

     public static void C(){
          SET();
          ...
     }

     public static void SET(){

     }

}

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

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 8

+5

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

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

private static void SetThen(Action action){
    SETの内容
    action();
}

を用意して

public void A(){
    SetThen(()=>{処理});
}
public void B(){
    SetThen(()=>{処理});
}
public void C(){
    SetThen(()=>{処理});
}

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+3

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

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

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+2

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

static Sample(){
     SET();
}

追記

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

    public abstract class Sample
    {
        public void Run()
        {
            this.SET();
            this.Action();
        }

        private void SET()
        { }

        protected abstract void Action();
    }

    public class A : Sample
    {
        protected override void Action()
        {
            // A...
        }
    }

    public class B : Sample
    {
        protected override void Action()
        {
            // B...
        }
    }

    public class C : Sample
    { ... }

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/26 22:04

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

    キャンセル

  • 2018/06/27 07:48

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

    キャンセル

+2

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

【追伸】

訂正: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/26 10:38

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

    キャンセル

  • 2018/06/26 10:59

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

    キャンセル

+2

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

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

public static class Sample
{
    public static void Invoke(Action iAction)
    {
        SET();
        iAction();
    }
        :
        :
}

static void Main(string[] args)
{
    Sample.Invoke(Sample.A);
}


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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

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

#なにをしたいんだろう

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

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

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

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

public class Program
{
    static void Main()
    {
        SampleClass.GetInstance().SampleMethod("テスト実行");
        Console.ReadLine();
    }
}

//実行対象クラス
[MyAspect]
public class SampleClass : ContextBoundObject
{
    private static SampleClass _instance = new SampleClass();

    public static SampleClass GetInstance()
    {
        return _instance;
    }

    private SampleClass()
    {

    }

    public string SampleMethod(string str)
    {
        Console.WriteLine(str);
        return null;
    }
}


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

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

 追記

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 90.50%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • C#

    7119questions

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