Does using Dictionary in editor window to display list of GameObjects is a good way?

everything is working find as I wanted. this is something I did to search for script name.
it will filter and show all gameobjects with the script attached to it.

my question if my code written the right way? if using Dictionary is good idea? and if not using Dictionary how to do it?

screenshot:

this is the code:

using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System;
using System.Linq;
using System.Xml;
using static Unity.VisualScripting.Member;
using Unity.VisualScripting;
using log4net.Util;

public class ScriptFinder : EditorWindow
{
    static ScriptFinder window;
    static Dictionary<GameObject, string> dictio = new Dictionary<GameObject, string>();
    Vector2 scrollPos;
    static List<int> num = new List<int>();
    static bool showPosition = true;

    [MenuItem("EditorUtility/Script Finder")]
    static void OpenScriptFinder()
    {
        window = (ScriptFinder)EditorWindow.GetWindow(typeof(ScriptFinder));

        MonoBehaviour[] scripts = UnityEngine.Object.FindObjectsOfType<MonoBehaviour>();
        foreach (MonoBehaviour script in scripts)
        {
            Type scriptType = script.GetType();
            var scope = scriptType.Namespace;
            if (scope == null || !scope.StartsWith("Unity"))
            {
                if (!dictio.Keys.Contains(script.gameObject))
                {
                    dictio.Add(script.gameObject, scriptType.Name);
                }
            }
        }
    }

    int counter = 0;
    string searchString;
    void OnGUI()
    {
        GUI.color = Color.white;
        GUILayout.FlexibleSpace();
        searchString = GUILayout.TextField(searchString, GUI.skin.FindStyle("ToolbarSeachTextField"));
        if (GUILayout.Button("", GUI.skin.FindStyle("ToolbarSeachCancelButton")))
        {
            searchString = "";
            GUI.FocusControl(null);
        }

        scrollPos =
            EditorGUILayout.BeginScrollView(scrollPos, false,true,
            GUILayout.ExpandWidth(true), GUILayout.Height(position.height));

        foreach (KeyValuePair<GameObject, string> pair in dictio)
        {
            EditorGUILayout.BeginHorizontal();

            if (searchString != null)
            {
                if (pair.Value.Contains(searchString, StringComparison.CurrentCultureIgnoreCase))
                {
                    
                    EditorGUILayout.ObjectField(pair.Key, typeof(GameObject), true);
                    
                    foreach (UnityEngine.Transform g in pair.Key.transform.GetComponentsInChildren<UnityEngine.Transform>())
                    {
                        
                    }

                    num.Add(EditorGUILayout.TextField(pair.Value).Length);
                }
            }
            else
            {
                EditorGUILayout.ObjectField(counter.ToString(), pair.Key, typeof(GameObject), true);
                num.Add(EditorGUILayout.TextField(pair.Value).Length);
                if (counter != dictio.Count)
                {
                    counter++;
                }
            }

            EditorGUILayout.EndHorizontal();
        }

        GUILayout.EndScrollView();
    }
}

@HaimHadad1972 - Using a Dictionary to display a list of GameObjects in an editor window is not a bad idea, especially if it’s working as you intended. However, there might be a more efficient way to achieve the same result.

Instead of using a Dictionary, you can use a List of custom class objects, which will store both the GameObject and the script’s name. This approach will be simpler and easier to manage. Here is an example of how you can modify your code:

Step 1: Create a custom class to hold the GameObject and the script’s name.

public class GameObjectAndScriptName
{
    public GameObject GameObject;
    public string ScriptName;

    public GameObjectAndScriptName(GameObject gameObject, string scriptName)
    {
        GameObject = gameObject;
        ScriptName = scriptName;
    }
}

Step 2: Replace the Dictionary with a List of the custom class objects in your ScriptFinder class.

public class ScriptFinder : EditorWindow
{
    static ScriptFinder window;
    static List<GameObjectAndScriptName> gameObjectAndScriptNames = new List<GameObjectAndScriptName>();
    // Rest of the code...
}

Step 3: Update the OpenScriptFinder() method to use the custom class.

static void OpenScriptFinder()
{
    window = (ScriptFinder)EditorWindow.GetWindow(typeof(ScriptFinder));

    MonoBehaviour[] scripts = UnityEngine.Object.FindObjectsOfType<MonoBehaviour>();
    foreach (MonoBehaviour script in scripts)
    {
        Type scriptType = script.GetType();
        var scope = scriptType.Namespace;
        if (scope == null || !scope.StartsWith("Unity"))
        {
            if (!gameObjectAndScriptNames.Any(x => x.GameObject == script.gameObject))
            {
                gameObjectAndScriptNames.Add(new GameObjectAndScriptName(script.gameObject, scriptType.Name));
            }
        }
    }
}

Step 4: Update the OnGUI() method to use the List of custom class objects.

void OnGUI()
{
    // ... Rest of the code ...

    foreach (GameObjectAndScriptName item in gameObjectAndScriptNames)
    {
        EditorGUILayout.BeginHorizontal();

        if (searchString != null)
        {
            if (item.ScriptName.Contains(searchString, StringComparison.CurrentCultureIgnoreCase))
            {

                EditorGUILayout.ObjectField(item.GameObject, typeof(GameObject), true);

                foreach (UnityEngine.Transform g in item.GameObject.transform.GetComponentsInChildren<UnityEngine.Transform>())
                {

                }

                num.Add(EditorGUILayout.TextField(item.ScriptName).Length);
            }
        }
        else
        {
            EditorGUILayout.ObjectField(counter.ToString(), item.GameObject, typeof(GameObject), true);
            num.Add(EditorGUILayout.TextField(item.ScriptName).Length);
            if (counter != gameObjectAndScriptNames.Count)
            {
                counter++;
            }
        }

        EditorGUILayout.EndHorizontal();
    }

    // ... Rest of the code ...
}

With these changes, your code should still work as expected, and you no longer need to use a Dictionary. The List of custom class objects will make it easier to manage and understand the relationship between GameObjects and their script names.

This is just an alternative though, there isnt really anything wrong with the way you are doing it now if its working for you, remember the saying, “don´t fix what aint broken”. Just thought you might be interested in alternatives. Before attempting this remember to backup your project.