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

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

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

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

Q&A

解決済

5回答

1804閲覧

C#で引数をthisに限定する方法

DeadEndShoot666

総合スコア203

C#

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

0グッド

0クリップ

投稿2018/07/01 00:27

編集2018/07/01 01:45

追記:質問内容が不明瞭だったので弾きたい処理と場所を明確にして、意図が伝わりやすいようにReciever側をstaticに変更して、Sender側の関数はコンストラクタに変更しました

class Other{ void other(){ //弾きたい処理 Receiver.Receive(new Sender()); } } class Sender{ public Sender(){ //通したい処理 Receiver.Receive(this); //弾きたい処理 Receiver.Receive(new Sender()); } } static class Receiver{ static public void Receive(Sender sender){ if(//引数と送ってきた側のインスタンスが一致しない){ return; } //メイン処理 } }

このときに引数がthisでないというか自分以外を渡そうとしてきたときに弾いてやるようにしたいのですが、何か良い方法はありますでしょうか

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2018/07/01 01:10

どういうシナリオで、どこではじきたいのですか? それによって話が変わってくると思うのですが。
DeadEndShoot666

2018/07/01 01:44

不明瞭で申し訳ありません。不定期に多数生成されるSenderをReciever側で管理して逐一比較したりしています。Recieve関数内で弾きたいです
退会済みユーザー

退会済みユーザー

2018/07/01 02:08 編集

Reciever クラス、Recieve メソッドを static に変更したようですが、static にする必要がありますか? 本当はどうしたいのでしょう? 最初の質問にあったようにインスタンスクラス、メソッドにしたいということはないのですか?
maisumakun

2018/07/01 02:25

あくまでデバッグ用に仕込むものでしょうか?(性質上、コードを書く時点で注意できれば、製品版でこのチェックをかける必要はない、とも読めます)
DeadEndShoot666

2018/07/01 02:45

SurferOnWwwさん>例を増やすのにクラスを増やしてしまったのと、元はシングルトンなのでstaticに変更しました。今回Recieve側を新しく作ることはありません。
DeadEndShoot666

2018/07/01 02:45

maisumakunさん> はい。実際のところ注意していれば何の問題もありませんしほぼ間違わないと思うのですが。publicにしたのでどこからでも呼べてしまって少し気持ちが悪いのと、送り主を担保する方法が何かないかと気になっているのがメインです。
guest

回答5

0

Reciever クラス、Recieve メソッドを static にすると「鶏が先か卵が先か」的な話になって自分には上手い案は思いつきません。

質問者さんのご期待には沿えないかもしれませんが、以下のようにインスタンスクラス・インスタンスメソッドにしてはいかがでしょう?

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; using System.Xml; using System.Collections; namespace ConsoleApplication4 { public class Sender { public Receiver Receiver { get; set; } public Sender() { this.Receiver = new Receiver(this); } } public class Receiver { private Sender s = null; public Receiver() { } public Receiver(Sender sender) { this.s = sender; } public void Receive(Sender sender) { Console.WriteLine(((object)s == (object)sender).ToString()); } } class Program { static void Main(string[] args) { Sender sender = new Sender(); sender.Receiver.Receive(sender); sender.Receiver.Receive(new Sender()); // 結果は: // True // False } } }

投稿2018/07/01 03:48

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

DeadEndShoot666

2018/07/01 15:20

実際リスト化して管理しているので、これをループで回せば解決できそうです。ありがとうございました。
guest

0

ベストアンサー

回答になっているか、全く自信がないですが、、、

まず、Senderのコンストラクタについて、

C#

public Sender(){ //通したい処理 Receiver.Receive(this); //弾きたい処理 Receiver.Receive(new Sender()); }

"弾きたい処理" ですが、コンストラクタ内で newしているので、多重になりませんか? (その結果、無限ループ? ) --> 記述できないコードでは?

C#

void other(){ //弾きたい処理 Receiver.Receive(new Sender()); }

ここでも、new なので、まず、コンストラクタが呼び出され、その中で、Receiver.Receive(this) が呼ばれる。(これは OK?) この時に渡された オブジェクトはどこかに保存されるのでは、と推定します。次に newされたオブジェクトを引数に呼ばれるので、同じオブジェクトになると思います。以前に呼び出されたのと同じオブジェクトかどうか検査したら、どうでしょうか?

外していたら、申し訳ありません。

投稿2018/07/01 08:06

pepperleaf

総合スコア6383

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

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

DeadEndShoot666

2018/07/01 14:40

たしかに無限ループになりそうな上に、実際はReciever側で受け取った物はその後リスト化しているので重複チェックで弾いておけば良いですね。送り主を特定する方法が気になって他の部分が整理できていませんでした。ありがとうございます。
guest

0

シナリオが理解できないので(はじけなかったら何が困るのでしょう?)すが、追記部分に対してコメントします。

  1. publicにすることの是非

どういう理由で弾きたいのか、弾けないと何が困るのかにかかってきますが、引数の内容をみてはじかないと困るようなそういうReceiveをpublic,staticにして問題ないのでしょうか(ミスではなく何らかのバグやロジック上のその場しのぎの手当のために、必要悪として悪用されたりしないのでしょうか?)
(Receiverのnamespaceをかえて、Otherではusingしないとか)
0. 形式的に検知する方法の一つのアイデアとして。
Receiver.Receive(new Sender())とかかせるから、そういうリスクがあるわけで、thisというSenderクラス自身にとっては動的に変動しないものなら、引数をとらないSend()みたいなラッパを作ればいいのではないでしょうか(まあでもpublic staticならいくらでも呼べるから、それこそ無駄かもしれませんが)

投稿2018/07/01 14:18

papinianus

総合スコア12705

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

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

DeadEndShoot666

2018/07/01 15:29 編集

たしかに知識不足とすでにできあがったコードを書き換えたくないというところからpublicをその場しのぎにしようとしている感があります。StackFrameで呼び出しもとのクラスを取得するところまでは質問する以前に調べられたのですが、クラスが取得できるのならもう少し厳密に呼び出し元が特定できるのではないかと思ったのですが
guest

0

ReceiverをSender内のclassとし、Sender生成時に乱数のような札を持っておくのはいかがでしょうか。
そしてReceiverは渡されたインスタンス内の札と、自分がいるSender内の札を比較して明らかにする。

抽象的に申し上げるなら、以下の通り。
1.判定者をとあるグループに所属させる。
2.とあるグループは実体化した瞬間に"札"を作る。
3.判定者は渡されたグループの持つ"札"が自身の所属しているグループの"札"と一致しているか見る。

※念のため補足します。
上記の方法は以下の思想を採用しています。
「(Receiverはインナークラスであり)アウタークラスのみアクセスする想定」

投稿2018/07/01 03:13

編集2018/07/01 03:23
sandboxA

総合スコア74

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

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

0

こんにちは。

Receive()関数が、その引数が特定の値であることをチェックするということはその特定の値をどこかに保持しておく必要があります。
Receiverがクラスなのですから、メンバ変数として保持するのが一般的と思います。この場合の解は既にSurferOnWwwさんが回答されている通りです。

他にはstaticメンバ変数としてthisを保持する方法も考えられると思います。
乱用するのは危険なのでお勧めではないです。staticなpublicメンバ変数やstaticなpublicメンバ関数は、要するにC言語のグローバル変数やグローバル関数と同等なものですから、乱用は避けるべきです。

投稿2018/07/01 07:45

Chironian

総合スコア23272

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問