@TomatoPizza

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

VB.NETでListに追加したインスタンス同士をリンク(同期)させたい

解決したいこと

現在オブジェクト指向を勉強しながら
VB.NET(.NET framework4.8)でWindowsアプリケーションを作成中で、
現在困っていることは 2つのListにインスタンスを追加し、その後片方のListから要素を削除したらもう片方のListにも同じインスタンスがあれば消えてほしいです、

発生している問題

VB.NET
Public List1 As New List(Of class1) 'Line(Class)を格納する配列1
Public List2 As New List(Of class1) 'Line(Class)を格納する配列2
VB.NET
Dim test1 as New Class1 'インスタンスの作成
Dim test2 as New Class1 'インスタンスの作成
Dim test3 as New Class1 'インスタンスの作成

'List1に要素を追加
List1.Add(test1)
List1.Add(test2)

'List2に要素を追加
List2.Add(test2)
List2.Add(test3)


test2.Name = "test" '名前を変えたらList1,2ともに変わる
test2 = Nothig 'Nothingを代入してもListからは消えない

「test2 = Nothig」のようなこと実行したらList1,List2に格納されているtest2も勝手に消えてほしい!
このようにインスタンス同士をリンクさせることはVB.NETでは実現不可能なのでしょうか??

Listじゃなくてこんな方法なら同じような事できるよ!的な意見もいただきたいです。
よろしくお願いします。

自分で試したこと

下記サイトを参考にクラス内にDisposeを実装し、NothigではなくDisposeを実行してもList1,2の要素は変化ありませんでした。

最近オブジェクト指向を勉強始めたばかりで質問としておかしな点も多々あるかと思いますがよろしくお願いします。

0 likes

2Answer

List1とList2でRemoveを実行するだけでよいと思いますが。
変な事をしようとして、物事を複雑化していませんか?

0Like

Comments

  1. @TomatoPizza

    Questioner

    回答ありがとうございます。
    すみません、説明不足でした。
    実際の困っているプログラムでは
    Listは複数あり、さらに多次元配列のため1ずつ探して削除するのが面倒だったため、一つを削除したら同じインスタンスは消えてほしいと思って質問させていただきました。

  2. その複数あるListで配列なりListなりを作成し、ループで回してRemove実行すればよいので別に面倒でもなんでもないと思いますが。

  3. @TomatoPizza

    Questioner

    はい、おっしゃる通り今現在はループを回してRemoveを実行しています。
    もっと短く記述する方法があるかもしれないと思って質問させていただきました。
    そのような動作する機能はないのでしょうね。ありがとうございました。

  4. List側は、中のインスタンスのNameが変わろうが知ったこっちゃないので、何もしてくれません。
    Class1側でName変更イベントを実装し、Listを継承した独自のListを作成してName変更のイベントハンドラを登録して、NameがNothingになった時にインスタンス削除させるという事は可能でしょうが、仕組みとしては普通にRemoveするより大掛かりになるでしょうし、短く記述とはならないですね。

  5. @TomatoPizza

    Questioner

    なるほど。たしかにListの継承するくらいならRemoveって感じですね
    ありがとうございました。

  6. 逆転の発想で、Class1側に自分自身を追加したList覚えさせておくとか…

    Public Class Class1
        Implements IDisposable
    
        '自分のインスタンスを保持しているListを記憶させるList
        Private _ListParent As New List(Of List(Of Class1))
    
        Public Sub New(name As String)
            Me.Name = name
        End Sub
    
        Public Property Name As String
            Get
                Return _Name
            End Get
            Set(value As String)
                If _Name <> value Then
                    _Name = value
                    If value Is Nothing Then
                        Dispose() 'NameがNothingになったら解放
                    End If
                End If
            End Set
        End Property
        Private _Name As String
    
        Public Sub AddToList(list As List(Of Class1))
            'Listに自身を追加するついでに、追加したListを記憶
            list.Add(Me)
            _ListParent.Add(list)
        End Sub
    
        Public Sub Dispose() Implements IDisposable.Dispose
            If _ListParent Is Nothing Then
                Return
            End If
    
            '自身のインスタンスを記憶した全てのListから削除
            For Each list In _ListParent
                list.Remove(Me)
            Next
            _ListParent = Nothing
        End Sub
    
    End Class
    
    Public Class Test
        Private List1 As New List(Of Class1)
        Private List2 As New List(Of Class1)
    
        Public Sub Run()
    
            Dim test1 As New Class1("test1")
            Dim test2 As New Class1("test2")
            Dim test3 As New Class1("test3")
    
            'List1に要素を追加
            test1.AddToList(List1)
            test2.AddToList(List1)
    
            'List2に要素を追加
            test2.AddToList(List2)
            test3.AddToList(List2)
    
            test2.Name = Nothing
    
            Console.WriteLine(List2(0).Name) 'test3
        End Sub
    
    End Class
    
    Public Class Program
    
        Shared Sub Main()
            Dim test = New Test
            test.Run()
        End Sub
    
    End Class
    
  7. @TomatoPizza

    Questioner

    動き確認しました!
    そうです!!こういうの欲しかったっす!!
    ありがとうございます:sob:

List1,List2に格納されているtest2も勝手に消えてほしい!

できなくはないけど、仕組みが複雑になり守らなきゃいけない決まり事ができたり何もいいことないです。

ループを回してRemove
もっと短く記述する方法

Dim ListArray = {List1, List2}  '削除対象リストの配列

'test2が存在しないListでRemoveしてもエラーにはならない
Array.ForEach(ListArray, Sub(list) list.Remove(test2))

VB.NETは簡単な処理でも複数行になることがよくあるので、一行で済ませられるとちょっとうれしい。

0Like

Comments

  1. @TomatoPizza

    Questioner

    ご回答ありがとうございます!
    短く書けるとちょっとうれしいですよね。
    (実は少し前に自分で関数作ったあとにそのままChatGPTにも同じもの作らせたのですが3行ほど短く可読性の高いの出力してきました:confounded:)

Your answer might help someone💌