泛型指针
本文关键字:指针 泛型 | 更新日期: 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模式。
不要使用指针。
如果你使用普通的引用,并且总是通过类中的属性与值交互,一切都会正常工作。