1

First, yes, I have seen these posts:
Is there an easy way in C# to have conditional compilation symbols based on OS version
Conditional compilation depending on the framework version in C#
but they do not target the direction I am looking for.

What I am looking for specifically is variable _type_ qualification via OS version:

public struct REPASTESPECIAL
{
     UInt32   dwAspect;
#if WINVER >= 6.0
     UIntPtr  dwParam;
#else
     UInt32   dwParam;
#endif 
}

I do not wish to revert to something like this:

public struct REPASTESPECIAL<T>
{
     UInt32     dwAspect;
     T dwParam;
}
// return type by OS version
public static Type GetRePasteSpecial_ParamType()
{
    if (Environment.OSVersion.Version.Major >= 5) return typeof(IntPtr);
    else return typeof(UInt32);
}

...as that would permit programmers to use any object of Type T when I desire dwParam to be an IntPtr or an UInt32 object only, but if I must then so be it, and make this a reference for others looking for the same.

Community
  • 1
  • 1
TekuConcept
  • 1,264
  • 1
  • 11
  • 21

2 Answers2

4

No - conditional compilation works at compile time, whereas it looks like you're after something which works at execution time.

EDIT: Just thinking about it, you could use conditional compilation in one sense: you could encapsulate this as far as possible in its own assembly, and compile it two ways, producing two separate assemblies. Then at install time (or whatever) install the right assembly. It's hard to know how feasible that is without knowing what kind of app you're writing though.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • If that is the case, then @ChristopherWalker would need to revert to something along the lines of his second code example. An `UberRuntimeConcreteTypeDucker` perhaps. – bluevector Jun 01 '12 at 19:00
  • @jonnyGold: Potentially, yes. Or some completely different scheme - but definitely *not* conditional compilation. – Jon Skeet Jun 01 '12 at 19:01
  • If I would use the second example, the question would lie in how to allow programmers to only use one of the two variable types applicable... – TekuConcept Jun 01 '12 at 19:11
  • You couldn't syntactically stop them. You would have to rely on them following the rules. Unit tests and some automated `grepping` for rule violations can help in your CI build process. – bluevector Jun 01 '12 at 20:03
  • So perhaps ArgumentException("Invalid Type Object"), something like that? – TekuConcept Jun 02 '12 at 00:41
2

Answer to: "I have some ugly logic that I'm afraid will be misused when I expose it to others"

Consider exposing nice and usable API which does not let any misuse. Declare all interop types as inner classes and structures of implementation f you nice API, there is not much value to make innermost classes like REPASTESPECIAL to be publicly visible/usable.

This way you can hide ugly class/struct types and dynamically pick OS specific implementation if needed.

If this educational project - than it would be good place to learn about dependency injection to configure correct implementation at run-time.

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
  • So by what you are suggesting: the use of 'internal' for the struct and just ship out a compiled dll with a public wrapper? `internal struct REPASTESPECIAL` `{ UInt32 dwAspect; T dwParam; }`
    @EDUCATION: I am attempting to grasp the full potential of RichEdit controls in C# - http://msdn.microsoft.com/en-us/library/windows/desktop/ff486017(v=vs.85).aspx - I just finished building a UserUtils class with as many of the structs, messages, and other codes and methods. I then use that class in an extended RichTextBox control.
    – TekuConcept Jun 02 '12 at 00:33
  • Depends on your goals. If you want usable API - you need to work on creating one, if you just want to have helper objects to deal with RichEdit mostly for yourself - raw structures and UserUtils class are likely good enough for that. I.e. FileStream object could have been made as set of wrapper methods over CreateFile/ReadFileEx functions, but instead it made into one of Stream classes sharing common interface and as result integrated with the rest of IO objects like readers and writers. – Alexei Levenkov Jun 02 '12 at 00:54