【问题标题】:C# accessing array of static objectsC#访问静态对象数组
【发布时间】:2018-11-10 23:27:48
【问题描述】:

所以我正在开发一个基于文本的游戏,我遇到了在运行时没有正确填充对象的问题。我不完全确定为什么会这样,但这里是代码:

public class Area
{
    public List<Area> options;
    public string name;
    public string text;
    public uint time;

    private void loadOptions()
    {
        MainWindow.app.options.Children.Clear();
        for(int i = 0; i < options.Count(); i++)
        {
            Button b = new Button();

            b.Content = options[i].name;
            b.Name = "b"+i;
            b.Click += new RoutedEventHandler(optionClick);

            MainWindow.app.options.Children.Add(b);
        }
    }

    private void optionClick(object sender, EventArgs e)
    {
        Button clicked = (Button)sender;
        int index = Int32.Parse(clicked.Name.Split('b')[1]);
        options[index].load();
    }

    public void load()
    {
        loadOptions();
        MainWindow.app.mainText.SelectAll();
        MainWindow.app.mainText.Selection.Text = text;
    }
}

这是 Area 类的逻辑部分,我将所有其他区域保存在一个单独的文件中,在 Areas 类中,如下所示:

public static class Areas
{
    public static Area opening = new Area()
    {
        name = "Opening",
        text = "This is the first area, just a test for now, but will be fully filled out at a later time",
        time = 0,
        options = new List<Area>()
        {
            second
        }
    };

    public static Area second = new Area()
    {
        name = "second",
        text = "this is the second area for stuffs and stuffs",
        time = 0,
        options = new List<Area>()
        {
            opening
        }
    };
}

两者都是同一个命名空间的一部分,但为了便于阅读,它们位于不同的文件中。这个想法是选项数组包含玩家可以从该菜单进入的所有可能的菜单。第一个测试区的代码是这样的:

public Area test = new Area()
    {
        text = "This is yet another test to test stuffs and things and places",
        time = 0,
        options = new List<Area>
        {
            Areas.opening
        }
    };

并且加载正确,但是一旦我单击按钮,整个事情就会崩溃并引发空引用异常。

以下是错误的详细信息:

    System.NullReferenceException
  HResult=0x80004003
  Message=Object reference not set to an instance of an object.
  Source=LostWorlds
  StackTrace:
   at LostWorlds.Area.loadOptions() in C:\Users\Max\source\repos\LostWorlds\LostWorlds\LostWorlds\MainWindow.xaml.cs:line 356
   at LostWorlds.Area.load() in C:\Users\Max\source\repos\LostWorlds\LostWorlds\LostWorlds\MainWindow.xaml.cs:line 373
   at LostWorlds.Area.optionClick(Object sender, EventArgs e) in C:\Users\Max\source\repos\LostWorlds\LostWorlds\LostWorlds\MainWindow.xaml.cs:line 368
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.UIElement.RaiseEvent(RoutedEventArgs e)
   at System.Windows.Controls.Primitives.ButtonBase.OnClick()
   at System.Windows.Controls.Button.OnClick()
   at System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(MouseButtonEventArgs e)
   at System.Windows.UIElement.OnMouseLeftButtonUpThunk(Object sender, MouseButtonEventArgs e)
   at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.ReRaiseEventAs(DependencyObject sender, RoutedEventArgs args, RoutedEvent newEvent)
   at System.Windows.UIElement.OnMouseUpThunk(Object sender, MouseButtonEventArgs e)
   at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
   at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
   at System.Windows.Input.InputManager.ProcessStagingArea()
   at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
   at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
   at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)
   at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
   at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
   at System.Windows.Application.RunDispatcher(Object ignore)
   at System.Windows.Application.RunInternal(Window window)
   at System.Windows.Application.Run(Window window)
   at System.Windows.Application.Run()
   at LostWorlds.App.Main()

根据我收集到的信息,使用静态类 Areas 中的对象填充区域的选项列表存在一些问题,每当我查看列表的值时,它都有一个为空的条目。

【问题讨论】:

  • 发布空引用异常的文本和堆栈跟踪。将有助于确定它发生的位置。
  • 刚刚编辑了原始帖子以包含异常的完整详细信息
  • 在Areas 类中,您尝试将second 添加到未声明的list&lt;Area&gt;
  • `MainWindow.app.options` 是否已初始化?在loadOptions() 的第一行放置一个断点,然后查看。您还可以从那里单步调试调试器,看看它在哪里中断,然后您会更好地了解未初始化的内容。
  • 这是 C# 没有提升声明的问题吗?

标签: c# arrays nullreferenceexception


【解决方案1】:

我意识到这是提升的问题,因为在声明“second”之前“opening”引用了“second”,“opening”没有任何东西可以填充自己,因此返回了一个空引用。所以解决方法如下:

public static Area second = new Area()
    {
        name = "second",
        text = "this is the second area for stuffs and stuffs",
        time = 0,
        options = new List<Area>()
        {
            opening
        }
    };

    public static Area opening = new Area()
    {
        name = "Opening",
        text = "This is the first area, just a test for now, but will be fully filled out at a later time",
        time = 0,
        options = new List<Area>()
        {
            second
        }
    };

还不完全确定如何使引用具有循环性,但我相信我能弄明白。

【讨论】:

  • 看起来确实有点奇怪。为什么这些必须是周期性的?
  • 我想它不一定需要是循环的,也绝对不是两个元素之间的循环,但是,在开发的后期,我可能希望有区域循环(可能是 3 个循环-5 个区域左右),这将允许更有趣的游戏。另外,如果我可以有类似“回家”选项的东西,那就太好了,这将是对中心区域的引用。
  • 你怎么知道什么时候停止循环?
  • 好吧,程序只会根据用户的请求在循环中前进,并且会有多个分支路径,当前代码只是一个测试sn-p,以便在小范围内测试边缘情况人口。所以,快速的答案是当玩家想要时
  • 实际上...对于“回家”的选项,我可以硬编码那个
猜你喜欢
  • 2020-05-01
  • 2018-04-07
  • 1970-01-01
  • 1970-01-01
  • 2022-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-31
相关资源
最近更新 更多