泛型指针

本文关键字:指针 泛型 | 更新日期: 2023-09-27 18:18:42

好的,所以我想做一个泛型类,将改变数据类型的值。我想这样做的原因是,我可以有撤消和重做方法。我可以为我需要的每个值类型编写一个类。即double, int…但是,如果我能创建一个泛型类来做这件事,那就容易多了。

这是我的

class CommandChangeDouble : Command
{
    double _previous;
    double _new;
    double* _objectRef;
    public unsafe CommandChangeDouble(double* o, double to)
    {
        _objectRef = o;
        _previous = *o;
        _new = to;
        *_objectRef = _new;
    }
    public unsafe void Undo()
    {
        *_objectRef = _previous;
    }
    public unsafe void Redo()
    {
        *_objectRef = _new;
    }
}

这是我想要的

class CommandChangeValue<T> : Command
{
    T _previous;
    T _new;
    T* _objectRef;
    public unsafe CommandChangeValue(T* o, T to)
    {
        _objectRef = o;
        _previous = *o;
        _new = to;
        *_objectRef = _new;
    }
    public unsafe void Undo()
    {
        *_objectRef = _previous;
    }
    public unsafe void Redo()
    {
        *_objectRef = _new;
    }
}

,但这给了我错误错误"不能取的地址,得到的大小,或声明一个指针的托管类型('T')"

是否有更好的方法来做这件事或解决这个错误的方法?

泛型指针

对于记录,您可以使用以下方法获得指向泛型类型或任何其他类型的指针....

    /// <summary>
    /// Provides the current address of the given element
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="t"></param>
    /// <returns></returns>
    [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
    public static System.IntPtr AddressOf<T>(T t)
        //refember ReferenceTypes are references to the CLRHeader
        //where TOriginal : struct
    {
        System.TypedReference reference = __makeref(t);
        return *(System.IntPtr*)(&reference);
    }
    [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
    static System.IntPtr AddressOfRef<T>(ref T t)
    //refember ReferenceTypes are references to the CLRHeader
    //where TOriginal : struct
    {
        System.TypedReference reference = __makeref(t);
        System.TypedReference* pRef = &reference;
        return (System.IntPtr)pRef; //(&pRef)
    }

我已经使用它们和其他一些来实现与数组一起使用的切片形式。

c# 7.3用新的泛型约束unmanaged解决了这个问题。

基本上它允许这样做:

void Hash<T>(T value) where T : unmanaged
{
    // Okay
    fixed (T* p = &value) 
    { 
        ...
    }
}

文档

不提供指向值的指针,而是提供setter:

class CommandChangeValue<T> : Command
{
    T _previous;
    T _new;
    Action<T> _set;
    public CommandChangeValue(T value, Action<T> setValue, T newValue)
    {
        _previous = value;
        _new = newValue;
        _set = setValue;
        setValue(_new);
    }
    public void Undo() { _set(_previous); }
    public void Redo() { _set(_new); }
}

// ...
double v = 42;
var c = new CommandChangeValue(v, d => v = d, 99);

不要使用指针,正如另一个答案和评论中所说的那样。如果你想在你的应用程序中有一些撤销/重做功能,你可能想看看Memento模式。

不要使用指针。

如果你使用普通的引用,并且总是通过类中的属性与值交互,一切都会正常工作。