【问题标题】:Reference to a refrence type in .net?引用.net 中的引用类型?
【发布时间】:2009-09-18 17:48:05
【问题描述】:

所以我想要一个指向指针的指针。

我有一个在一个对象中更新的类。在另一个对象中,我想要引用原始类中对象的当前版本。这是我正在做的事情的简化版本。

Public Class Foo
    'conaints information

End Class

Public Class myMainApp
    Dim myHelper As HelperClass
    Dim currentFoo As Foo

    Private Sub init()
        currentFoo = New Foo()
        myHelper = New HelperClass(currentFoo)
    End Sub

    Private Sub UpdatingUI()
        currentFoo = GetFooFromContext()
    End Sub

    Private Function GetFooFromContext() As Foo
        Return New Foo()
    End Function
End Class


Public Class HelperClass
    Private myFoo As Foo

    Public Sub New(ByVal aFoo As Foo)
        myFoo = aFoo
    End Sub
End Class

如果 thise 是 C++,currentFoo 将是 Foo*,HelperClass 的 myFoo 将是 Foo**,因此每当我们将 currentFoo 的引用更新为新对象时,HelperClass 也将访问这个新对象。

在 .net 世界中是否有语法来实现这一点?

【问题讨论】:

    标签: .net pointers reference


    【解决方案1】:

    没有直接的等价物。

    最好的选择通常是让 HelperClass 实际上保留对主类的引用,并根据需要从主类的属性中读取/写入 Foo。这样,它就引用了持有 Foo 的类,而不是 Foo 本身。但是,这仍然不一样,因为如果您更改主类“Foo”实例,您将失去对原始类的引用(除非您也保存了它)。

    【讨论】:

    • 我知道这是个好主意,但在这种实际情况下,主类是一个包含很多东西的表单,我只需要其中的几个对象。访问主窗体对于下一个人来说可能真的很危险。
    • 然后使用一个接口。如果主类实现了一个接口,您可以使用它来公开您希望的特定属性,并将表单作为接口而不是类传递。
    • 该场景中的另一个选项是定义一个仅包含您需要的表单属性的接口,让表单实现它,并在HelperClass 中使用对所述接口的引用。这将使耦合的数量明确并因此清晰。当然,仍然可以将接口引用转换为原始类,但这样做的人至少必须努力这样做,并希望停下来思考他们在做什么。
    • 那个界面创意很酷,我可能最终会使用它,或者类似的东西。绝对是我会努力藏在我的心理工具箱里的东西。
    【解决方案2】:

    Reed 的回答是处理这个问题的典型 C# 惯用方法,但如果你真的想要它,你可以随时引入你自己的“引用包装器”帮助器类:

    public class Reference<T> where T : class
    {
        public T Value { get; set; }
    }
    

    然后将currentFoomyFoo 都声明为Reference&lt;Foo&gt;,并确保currentFooreadonly,这样就没有人可以为其分配不同的Reference

    【讨论】:

    • 对于快速而肮脏的一次性解决方案(或者如果您没有泛型 - 即 .NET 1.x),使用单元素数组也可以,尽管不太清楚.
    【解决方案3】:

    您需要共享对具有 ​​Foo 作为属性的类的引用。抱歉用 C# 编写;-)

    class MyMainApp
        {
            private HelperClass myHelper;
            private FooBar myFooBar;
    
            public void Init()
            {
                myFooBar=new FooBar(new Foo());
                myHelper=new HelperClass(myFooBar);
            }
    
            public void UpdateFromUI()
            {
                myFooBar.CurrentFoo = GetFooFromContext();
                myHelper.DoSomethingWithTheFoo();
            }
    
            private Foo GetFooFromContext()
            {
                return new Foo();
            }
        }
    
        class FooBar
        {
            public Foo CurrentFoo;
    
            public FooBar(Foo new_foo)
            {
                CurrentFoo = new_foo;
            }
        }
    
        class HelperClass
        {
            private FooBar myFooBar;
    
            public HelperClass(FooBar new_foobar)
            {
                myFooBar = new_foobar;
    
            }
    
            public void DoSomethingWithTheFoo()
            {
                myFooBar.CurrentFoo.JumpThroughHoop();
            }
        }
    
        class Foo
        {
            public void JumpThroughHoop()
            {}
        }
    

    【讨论】:

    • 啊,是的,如果再增加一层抽象,一切都会更好。我看到这与我希望我的应用程序如何工作更接近,myFooBar 包含我需要的所有上下文信息。不幸的是,一切都是在没有中间层的情况下设置的,因此需要更多的工作来重组应用程序以使其像那样工作,但可能是解决方案。
    【解决方案4】:

    别再考虑指针了

    是的,您可以使用不安全的代码在 C# 中完全按照您的想法行事 - 但是说真的,不要

    Reed 的建议是迄今为止最好的;我怀疑如果有更多上下文,我们可以提出更好的解决方案,例如:

    • 为 currentfoo 使用属性
    • 设置 currentfoo 的值时,更改助手类的 foo 属性的值

    主要是我只是想强调这个问题的 omg-don't-do-that 方面 ;-)

    【讨论】:

    • 实际上,你不能使用 unsafe 来做到这一点,因为即使 unsafe 也不允许你声明指向托管类型的原始指针(对象引用是托管类型)。
    • @[Pavel Minaev]:我的立场是正确的,谢谢 - 更有理由停止考虑指针!
    猜你喜欢
    • 1970-01-01
    • 2012-07-20
    • 2012-01-29
    • 2012-08-06
    • 1970-01-01
    • 2012-04-23
    • 1970-01-01
    • 2011-06-06
    • 2010-11-10
    相关资源
    最近更新 更多