Replies: 17 comments
-
I think the primary issue here is that anything over Additionally, I'm trying to think of where literal IntPtr would be required, and it tends to be limited to well defined constant values (such as I do think, given that IntPtr is a CLR primitive type, having literal values makes sense. I'm just not sure of the overall use case here (even my own proposal on exposing the operators #48, is known to be a very niche use-case). |
Beta Was this translation helpful? Give feedback.
-
I'm confused; even when running 64-bit? And wouldn't the compiler be able to error if you're targeting x86, and warn if you're targeting AnyCPU? |
Beta Was this translation helpful? Give feedback.
-
Yes, only throws on 32-bit... However, even for interop code, you can generally write it in a way to make it portable (this is why you are using IntPtr in the first place, if you didn't care about platform portability, it is more efficient to just use int or long anyways since operators, constants, and various optimizations are available). I'm also honestly interested in a case where you need a large number IntPtr literals. Most of the interop code I've seen/written involves getting an IntPtr back from native code. When that IntPtr is a handle, the value is either valid (could potentially be any value) or invalid (represented by 0 or -1, generally). When it is used to represent something like size_t, I generally don't have a hardcoded value, and if I do, they are infrequent enough that doing (IntPtr)(value) for the initialization is sufficient. What I have found to be frequently in need of is the ability to perform basic arithmetic on IntPtr values, for when they represent something like a size_t. |
Beta Was this translation helpful? Give feedback.
-
I tried to capture that example in the issue from the Roslyn repo. My example was
My real use case is interoping with non-Microsoft libraries that use |
Beta Was this translation helpful? Give feedback.
-
I also can't resist saying "F# has it". |
Beta Was this translation helpful? Give feedback.
-
I understand the need for improvement in relation to interop and support for native sized integers in C#. I'm just trying to understand how this case would specifically improve it. Even in the example you gave, the best you're going to get is: public static readonly IntPtr CERT_CHAIN_POLICY_BASE = 1n;
public static readonly IntPtr CERT_CHAIN_POLICY_AUTHENTICODE = 2n;
public static readonly IntPtr CERT_CHAIN_POLICY_AUTHENTICODE_TS = 3n;
public static readonly IntPtr CERT_CHAIN_POLICY_SSL = 4n;
public static readonly IntPtr CERT_CHAIN_POLICY_BASIC_CONSTRAINTS = 5n;
public static readonly IntPtr CERT_CHAIN_POLICY_NT_AUTH = 6n;
public static readonly IntPtr CERT_CHAIN_POLICY_MICROSOFT_ROOT = 7n;
public static readonly IntPtr CERT_CHAIN_POLICY_EV = 8n;
public static readonly IntPtr CERT_CHAIN_POLICY_SSL_F12 = 9n;
[DllImport("Crypt32.dll")]
public static extern int CertVerifyCertificateChainPolicy(
[In] IntPtr pszPolicyOID,
[In] ref CERT_CHAIN_CONTEXT pChainContext,
[In] ref CERT_CHAIN_POLICY_PARA pPolicyPara,
[In, Out] ref CERT_CHAIN_POLICY_STATUS pPolicyStatus
); However, this is easily "improved" by doing the following instead (uses constants, the cast is optimized away, and abstracts the nitty gritty details from the consumer, even if that consumer is you). public enum CERT_CHAIN_POLICY : int
{
BASE = 1,
AUTHENTICODE = 2,
AUTHENTICODE_TS = 3,
SSL = 4,
BASIC_CONSTRAINTS = 5,
NT_AUTH = 6,
MICROSOFT_ROOT = 7,
EV = 8,
SSL_F12 = 9
}
[DllImport("Crypt32.dll")]
public static extern int CertVerifyCertificateChainPolicy(
[In] IntPtr pszPolicyOID,
[In] ref CERT_CHAIN_CONTEXT pChainContext,
[In] ref CERT_CHAIN_POLICY_PARA pPolicyPara,
[In, Out] ref CERT_CHAIN_POLICY_STATUS pPolicyStatus
);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool CertVerifyCertificateChainPolicy(
[In] CERT_CHAIN_POLICY pszPolicyOID,
[In] ref CERT_CHAIN_CONTEXT pChainContext,
[In] ref CERT_CHAIN_POLICY_PARA pPolicyPara,
[In, Out] ref CERT_CHAIN_POLICY_STATUS pPolicyStatus)
{
var result = CertVerifyCertificateChainPolicy(
(IntPtr)(pszPolicyOID),
ref pChainContext,
ref pPolicyPara,
ref pPolicyStatus
);
return (result != 0);
} Now, if we had constant IntPtr as well, I think this would be a different story entirely 😄 |
Beta Was this translation helpful? Give feedback.
-
Well at this point one could relaunch with this: public enum CERT_CHAIN_POLICY : IntPtr
{
BASE = 1,
AUTHENTICODE = 2,
AUTHENTICODE_TS = 3,
SSL = 4,
BASIC_CONSTRAINTS = 5,
NT_AUTH = 6,
MICROSOFT_ROOT = 7,
EV = 8,
SSL_F12 = 9
} So no cast is needed in any case 😄 |
Beta Was this translation helpful? Give feedback.
-
That would make my interop life nicer, but I know it's going to be hard to justify the language feature when interop is so rare. |
Beta Was this translation helpful? Give feedback.
-
@fanoI, how would that be possible. Just because you have language literal support, doesn't mean you have runtime literal support. I can declare Likewise, I can do If we had constant IntPtr (that is actual runtime literals) and enum was extended to support any runtime literal type, then I would think this would be reasonable 😄. Without the above, this becomes syntactic sugar with bad perf. |
Beta Was this translation helpful? Give feedback.
-
Isn't that what |
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
Looks like I was partially wrong on one thing though. The runtime does apparently have support for
However, I'm wondering how you would be expected to declare a |
Beta Was this translation helpful? Give feedback.
-
Ah, here it is:
So, it looks like this would work and the runtime has all the necessary 'stuff' already. The limitation is that all literal values would need to be size int32. |
Beta Was this translation helpful? Give feedback.
-
Which makes |
Beta Was this translation helpful? Give feedback.
-
@jnm2, the way those are extended are actually well defined: However, there is a bug here when overflow/underflow is enabled: https://github.com/dotnet/coreclr/issues/9591 |
Beta Was this translation helpful? Give feedback.
-
@vcsjones, it would be helpful if you could update the proposal to indicate that the runtime does currently support |
Beta Was this translation helpful? Give feedback.
-
IntPtr/UIntPtr should be represented as intptr/uintptr keywords and they should support all the same bitwise/arithmetic operations as the other integral types. Otherwise I simply continue using my custom "[U]IntPtrEx" struct with operator overloads and skip the topic. I can't imagine anyone being excited that C# is being limited by VB for academic reasons. |
Beta Was this translation helpful? Give feedback.
-
I propose that literal suffixes for IntPtr and UIntPtr be added. For example:
Where the literal is equivalent to
new IntPtr(2)
,new UIntPtr(2)
, andnew IntPtr(-1)
respectively.The primary need for this is platform invoke or any situation where native integers are used. Many Win32 APIs take magic handle values, or null (0n). This would also bring parity to F# which already supports this feature.
(copied from dotnet/roslyn#4273)
Beta Was this translation helpful? Give feedback.
All reactions