C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

【C#】メソッドから自分自身に代入する方法

[トピック内 11 記事 (1 - 11 表示)]  << 0 >>

■97026 / inTopicNo.1)  【C#】メソッドから自分自身に代入する方法
  
□投稿者/ tees (2回)-(2021/03/17(Wed) 14:55:35)

分類:[C#] 

メソッドからコンストラクタを使用して、
自分自身に代入する方法がありましたら教えてください。

public class Test
{
public int A { get; set; }

// コンストラクタ
public Test(int a)
{
A = a;
}

// メソッド
public Method(int a)
{
this = new Test(a); // これを実行したい
}

}

C#
VS2019
.Net5.0

引用返信 編集キー/
■97027 / inTopicNo.2)  Re[1]: 【C#】メソッドから自分自身に代入する方法
□投稿者/ furu (107回)-(2021/03/17(Wed) 15:06:10)
No97026 (tees さん) に返信
> メソッドからコンストラクタを使用して、
> 自分自身に代入する方法がありましたら教えてください。
自分自身には代入できません。

var test = Method(12345);

こういうことをしたいのなら
staticにして、生成したインスタンスを返すようにします。

public static Test Method(int a)
{
    retuen new Test(a);
}

引用返信 編集キー/
■97028 / inTopicNo.3)  Re[2]: 【C#】メソッドから自分自身に代入する方法
□投稿者/ tees (3回)-(2021/03/17(Wed) 15:35:50)
No97027 (furu さん) に返信

> var test = Method(12345);
> 
> こういうことをしたいのなら
> staticにして、生成したインスタンスを返すようにします。
> 
> public static Test Method(int a)
> {
>     retuen new Test(a);
> }

ご返信ありがとうございます。
var testのように一時変数に格納するのではなく、
this(自分自身)に反映させたいのが目的になります。
※初期化用のメソッドを別途作成してしまえば解決してしますが・・・。

引用返信 編集キー/
■97029 / inTopicNo.4)  Re[3]: 【C#】メソッドから自分自身に代入する方法
□投稿者/ Hongliang (1158回)-(2021/03/17(Wed) 15:40:34)
classでは不可能なので、妥協案なり代替案なりを用意する必要がありますね。
どちらを選ぶかは、そうしたい理由にもよりますが。

// 実はstructでは可能だったり。
引用返信 編集キー/
■97030 / inTopicNo.5)  Re[3]: 【C#】メソッドから自分自身に代入する方法
□投稿者/ 魔界の仮面弁士 (3012回)-(2021/03/17(Wed) 15:55:06)
No97026 (tees さん) に返信
> // メソッド
> public Method(int a)

それはメソッドの構文では無いですよね。
必要なのはどちらですか?

public void Method(int a)
public Test Method(int a)


No97028 (tees さん) に返信
> this(自分自身)に反映させたいのが目的になります。

今回の実装だと、
 public void Method(int a) => A = a;
で良いのでは。
引用返信 編集キー/
■97031 / inTopicNo.6)  Re[4]: 【C#】メソッドから自分自身に代入する方法
□投稿者/ tees (4回)-(2021/03/17(Wed) 15:58:43)
No97030 (魔界の仮面弁士 さん) に返信

>
> それはメソッドの構文では無いですよね。
> 必要なのはどちらですか?
>
> public void Method(int a)
> public Test Method(int a)

すみません、正しいメソッドはこちらになります。
public void Method(int a)


> ■No97028 (tees さん) に返信
>>this(自分自身)に反映させたいのが目的になります。
>
> 今回の実装だと、
>  public void Method(int a) => A = a;
> で良いのでは。

プロパティが一つだけであれば確かにその方法で良いのですが、
実際には無数のプロパティがあるためアドバイスをいただこうと思っていました。

引用返信 編集キー/
■97032 / inTopicNo.7)  Re[5]: 【C#】メソッドから自分自身に代入する方法
□投稿者/ 魔界の仮面弁士 (3013回)-(2021/03/17(Wed) 16:09:42)
No97031 (tees さん) に返信
> プロパティが一つだけであれば確かにその方法で良いのですが、
> 実際には無数のプロパティがあるためアドバイスをいただこうと思っていました。

無数とは言いますが、変更したいのは引数で指定されたメンバーだけなのですよね?


何のために this を書き換えたいと思っているのか、まず先に目的を教えてもらえないでしょうか。

メンバーの一部を書き換える事だけが目的なのか、
そうではなく、this が指し示す参照先を別インスタンスにしたいのか、
それとも、もっと何か特殊な理由があるのか…。


一部の値を差し替えただけの別インスタンスを作るのが目的なら、
class を record に変更し、with で初期化するという手もあるかと思います。

public Test Method2(int a) => this with { A = a };
引用返信 編集キー/
■97033 / inTopicNo.8)  Re[1]: 【C#】メソッドから自分自身に代入する方法
□投稿者/ 魔界の仮面弁士 (3014回)-(2021/03/17(Wed) 16:23:32)
2021/03/17(Wed) 17:53:55 編集(投稿者)

No97026 (tees さん) に返信
> this = new Test(a); // これを実行したい

言語仕様的にそれは叶わないわけですが、
もし仮に this が readonly で無かったとしたら、

 var c1 = new Test(100);
 var c2 = c1;
 c1.Method(50);
 Console.WriteLine($"{ReferenceEquals(c1, c2)}, {c1.A}, {c2.A}");

とした場合の動作は、どうなって欲しいのでしょうか。

案1) True, 50, 50
案2) False, 50, 100
案3) False, 50, 50


案1 が目的なら、this.A を書き換える形で代用してみてください。

案2 が目的なら、c2 への代入を参照コピーから複製コピーに変更するため、
 ICloneable.Clone を実装して呼び出すか、または、Method の戻り値として
 新規インスタンスを得られるようにすることで代用します。
 あるいは record 化して with 式で複製するのも良いかもしれません。

案3 となると、案2 と同様に別インスタンスを生成しつつ、さらに
 値の変更通知をコールバックさせるような仕組みを設ける必要がありそうです。
引用返信 編集キー/
■97034 / inTopicNo.9)  Re[2]: 【C#】メソッドから自分自身に代入する方法
□投稿者/ tees (5回)-(2021/03/17(Wed) 18:04:52)
No97033 (魔界の仮面弁士 さん) に返信
> 2021/03/17(Wed) 17:53:55 編集(投稿者)
> 
>無数とは言いますが、変更したいのは引数で指定されたメンバーだけなのですよね?

実際には引数も一つだけではありません。


>何のために this を書き換えたいと思っているのか、まず先に目的を教えてもらえないでしょうか。
>メンバーの一部を書き換える事だけが目的なのか、
>そうではなく、this が指し示す参照先を別インスタンスにしたいのか、
>それとも、もっと何か特殊な理由があるのか…。

目的としては引数で渡った値で自身のメンバーを書き換える(コピーする)ことです。


> 言語仕様的にそれは叶わないわけですが、
> もし仮に this が readonly で無かったとしたら、
> 
>  var c1 = new Test(100);
>  var c2 = c1;
>  c1.Method(50);
>  Console.WriteLine($"{ReferenceEquals(c1, c2)}, {c1.A}, {c2.A}");
> 
> とした場合の動作は、どうなって欲しいのでしょうか。
> 
> 案1) True, 50, 50
> 案2) False, 50, 100
> 案3) False, 50, 50
> 
> 
> 案1 が目的なら、this.A を書き換える形で代用してみてください。
> 
> 案2 が目的なら、c2 への代入を参照コピーから複製コピーに変更するため、
>  ICloneable.Clone を実装して呼び出すか、または、Method の戻り値として
>  新規インスタンスを得られるようにすることで代用します。
>  あるいは record 化して with 式で複製するのも良いかもしれません。
> 
> 案3 となると、案2 と同様に別インスタンスを生成しつつ、さらに
>  値の変更通知をコールバックさせるような仕組みを設ける必要がありそうです。

先ほど申し上げたように書き換えを行いたいですので案1になってほしいです。

引用返信 編集キー/
■97035 / inTopicNo.10)  Re[3]: 【C#】メソッドから自分自身に代入する方法
□投稿者/ 魔界の仮面弁士 (3015回)-(2021/03/17(Wed) 19:02:12)
2021/03/18(Thu) 10:41:37 編集(投稿者)

No97034 (tees さん) に返信
>> 無数とは言いますが、変更したいのは引数で指定されたメンバーだけなのですよね?
> 実際には引数も一つだけではありません。

ここでいう「無数」が、如何ほどを指すのかにもよりますが、
極端な話、言語仕様的には 6 万個の引数でも大丈夫ですよ。

x = new SampleClass("0000", "0001", ...., "FFFE", "FFFF");


型付 DataSet の TableAdapter などにおいては、自動生成されるメソッドが
数十個の引数を持つことも珍しくありません(数百個にもなりえる)。
流石に万単位の個数になると、言語仕様とは別のところで問題が生じる可能性がありますけれどね。
(Reflector や Obfuscator がエラーになったので、開発元に対応してもらった思い出)



> 目的としては引数で渡った値で自身のメンバーを書き換える(コピーする)ことです。

一部のプロパティのみを差し替えるのが主目的であれば、
record と with を使うのが便利かと思います。

※Deep Copy が必要なケースは要考慮。


いずれにせよ、「this を差し替える方法」は言語仕様的に不可能なので、
自身のメンバーを変更するための効率の良い方法を模索した方が建設的です。

実際の引数の渡し方は、どのようなものなのでしょうか。
引数の渡し方が複数パターンあったとしても、それは大抵、オーバーロードで解決できると思いますし、
必要に応じて、それを補佐するためのヘルパーメソッドを用意しておくのも手かと思います。

それとも、渡される引数の数が一定しておらず、可変なのでしょうか? (params あるいは __arglist )
あるいは 匿名型 や ExpandoObject などでパラメーターを動的に指定するようなケースでしょうか。


> 先ほど申し上げたように書き換えを行いたいですので案1になってほしいです。

案1 の場合、元のインスタンスを維持する必要があるわけですから、
書き換えメソッド内で「new Test」を呼び出す方針はありえないことになります。
そのため、with も使えないことになりますね。

相手が class Test や record Test ではなく struct Test なら、
こういう方法で自身を new で書き換える事もできますが…この方法だと、
ReferenceEquals は false になってしまいます。構造体なので当然ですが。

public static class TestExtensions
{
 public static void Method(this ref Test @this, int a) => @this = new Test(a);
}

もし、インスタンス管理がそもそも不要だというのであれば、
いっそのこと、static class にしてしまうという選択肢もあります。
(コピーはできなくなります)

しかし、あくまでインスタンス プロパティとしての実装が必要なのであれば、
クラスを new するのは最初の一回のみで、それ以降はそのインスタンスを
使いまわすことになるので、やはり this のメンバーを書き換える操作が必要でしょう。
引用返信 編集キー/
■97039 / inTopicNo.11)  Re[4]: 【C#】メソッドから自分自身に代入する方法
□投稿者/ tees (6回)-(2021/03/18(Thu) 16:18:45)
たくさんのアドバイスありがとうございます。
thisへの代入が無理ということですので、
各プロパティへの代入用メソッドを定義して使用するようにします。

解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ