我理解指针,并且很少需要在C#代码中使用它们.我的问题是:在一段代码中明确说明"不安全"的原因是什么.另外,为什么必须更改编译器选项以允许"不安全"代码?
结论: CLR(或语言规范)中的内容使得我们不能随时使用指针(很像C和C++)而不必键入"unsafe"并更改编译器选项?
澄清一下:我知道"不安全"和"安全"的代码是什么.这只是一个问题,为什么我们必须做所有额外的工作(好吧,不是那么多)只是为了能够使用这些功能.
我只是用C#做了一个Swap例程:
static void Swap(ref int x, ref int y)
{
int temp = x;
x = y;
y = temp;
}
Run Code Online (Sandbox Code Playgroud)
它与C++代码的作用相同:
void swap(int *d1, int *d2)
{
int temp=*d1;
*d1=*d2;
*d2=temp;
}
Run Code Online (Sandbox Code Playgroud)
所以是ref和out关键字,比如C#的指针,而无需使用unsafe代码?
我正在寻找一种方法来过滤出unsafe通过反射具有修饰符的方法.它似乎不是方法属性.
有办法吗?
编辑:似乎这个信息不在元数据中,至少我在IL中看不到它.但是反射unsafe器在C#视图中显示修改器.关于它是如何完成的任何想法?
编辑2:根据我的需要,我最终得到了一个检查,假设如果方法的某个参数是指针,或者返回类型是指针,那么该方法是不安全的.
public static bool IsUnsafe(this MethodInfo methodInfo)
{
if (HasUnsafeParameters(methodInfo))
{
return true;
}
return methodInfo.ReturnType.IsPointer;
}
private static bool HasUnsafeParameters(MethodBase methodBase)
{
var parameters = methodBase.GetParameters();
bool hasUnsafe = parameters.Any(p => p.ParameterType.IsPointer);
return hasUnsafe;
}
Run Code Online (Sandbox Code Playgroud)
当然,这不会处理在方法中执行不安全块的情况,但同样,我感兴趣的是方法签名.
谢谢!
我正在将几个非托管c ++ DLL导入到我的项目中,但导入的DLL具有相同的方法名称,这会导致编译器问题.例如;
unsafe class Myclass
{
[DllImport("myfirstdll.dll")]
public static extern bool ReturnValidate(long* bignum);
[DllImport("myseconddll.dll")]
public static extern bool ReturnValidate(long* bignum);
public Myclass
{
int anum = 123;
long passednum = &anum;
ReturnValidate(passsednum);
}
}
Run Code Online (Sandbox Code Playgroud)
现在我想做的就是在导入时重命名方法.就像是;
[DllImport("myseconddll.dll")]
public static extern bool ReturnValidate(long bignum) AS bool ReturnValidate2(long bignum);
Run Code Online (Sandbox Code Playgroud)
这可能吗?
我有一个包含int []数组的C#类(以及其他几个字段,但数组是主要的).代码经常创建此类的副本,并且分析显示复制此数组的Array.Copy()调用需要花费大量时间.我该怎么做才能让它更快?
数组大小非常小且恒定:12个元素.理想情况下,我喜欢类似C风格的数组:类本身内部的单个内存块(不是指针).这可能在C#中吗?(如果需要,我可以使用不安全的代码.)
我已经尝试过了:
1)使用UIn64和位移代替数组.(每个元素的值也非常小.)这确实使复制速度快,但整体上减慢了程序的速度.
2)为每个数组元素使用单独的字段:int element0,int element1,int element2等.同样,当我必须访问给定索引处的元素时,这总体上较慢.
fixed (int* pArray = &array[0])以下示例中的行是否固定整个数组,或者只是array[0]?
int array = new int[10];
unsafe {
fixed (int* pArray = &array[0]) { } // or just 'array'
}
Run Code Online (Sandbox Code Playgroud) msbuild似乎不允许我构建unsafe块,即使我.csproj指定:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
...
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
Run Code Online (Sandbox Code Playgroud)
我的构建命令是:
msbuild myProject.sln /p:Configuration=Release /p:Platform="Any CPU" /t:Clean,Build
Run Code Online (Sandbox Code Playgroud) 一个最近的问题一直在寻找构建自引用结构的能力.在讨论问题的可能答案时,一个可能的答案涉及使用UnsafeCell内部可变性然后通过a"丢弃"可变性transmute.
以下是这种想法的一个小例子.我对这个例子本身并不是很感兴趣,但是只需要一个更大的锤子就好了transmute,而不仅仅是使用UnsafeCell::new和/或UnsafeCell::into_inner:
use std::{
cell::UnsafeCell, mem, rc::{Rc, Weak},
};
// This is our real type.
struct ReallyImmutable {
value: i32,
myself: Weak<ReallyImmutable>,
}
fn initialize() -> Rc<ReallyImmutable> {
// This mirrors ReallyImmutable but we use `UnsafeCell`
// to perform some initial interior mutation.
struct NotReallyImmutable {
value: i32,
myself: Weak<UnsafeCell<NotReallyImmutable>>,
}
let initial = NotReallyImmutable {
value: 42,
myself: Weak::new(),
};
// Without interior mutability, we couldn't update …Run Code Online (Sandbox Code Playgroud) 我想使几个整数大小structS(即32个64位)是从原始非托管类型具有相同的尺寸能容易转变为/(即Int32与UInt32用于特别是32位大小的结构).
然后,结构将公开用于位操作/索引的附加功能,这些功能不能直接在整数类型上使用.基本上,作为一种语法糖,提高可读性和易用性.
然而,重要的部分是性能,因为这个额外的抽象应该基本上是0成本(在一天结束时,CPU应该"看到"相同的位,就好像处理原始的整数一样).
以下是struct我提出的最基本的内容.它没有所有功能,但足以说明我的问题:
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 4)]
public struct Mask32 {
[FieldOffset(3)]
public byte Byte1;
[FieldOffset(2)]
public ushort UShort1;
[FieldOffset(2)]
public byte Byte2;
[FieldOffset(1)]
public byte Byte3;
[FieldOffset(0)]
public ushort UShort2;
[FieldOffset(0)]
public byte Byte4;
[DebuggerStepThrough, MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe implicit operator Mask32(int i) => *(Mask32*)&i;
[DebuggerStepThrough, MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe implicit operator Mask32(uint i) => *(Mask32*)&i;
}
Run Code Online (Sandbox Code Playgroud)
我想测试这个结构的性能.特别是我想知道如果我使用常规的逐位算术,它是否可以让我快速获得单个字节 :( (i >> …
我正在编写一些不安全的Rust代码,因此我需要知道*const T和之间的确切区别*mut T。我以为是&T和&mut T(即,您T不能通过&T,句号进行变异),但事实并非如此!
例如,指针包装器NonNull<T>的定义如下(source):
pub struct NonNull<T: ?Sized> {
pointer: *const T,
}
Run Code Online (Sandbox Code Playgroud)
但是,可以*mut T通过as_ptr定义从以下包装器获取一个:
pub const fn as_ptr(self) -> *mut T {
self.pointer as *mut T
}
Run Code Online (Sandbox Code Playgroud)
该功能甚至没有标记为unsafe!我不允许强制从转换&T为&mut T(出于充分的理由!),但显然像这样强制转换指针是可以的。
该Nomicon提到了关于方差章是*const T和*mut T方差有所不同:
*const T:协变*mut T:不变的
这是指针类型之间的唯一区别吗?在我看来,这很奇怪。
指针类型之间到底有什么区别?是否有限制,*const T那*mut T …