Should I use int or UInt16? - c#

This may be somewhat trivial, but in C# do you prefer int or UInt16 when storing a network port in a variable? Framework classes use int when dealing with a network port although UInt16 actually represents the valid values.

signed (int / short etc, rather that uint / ushort) have the advantage of being CLS compliant, so that is recommended unless you have a good reason.
Re int vs short - in most cases it is more efficient to compute with int (or uint), since all the operators are optimised for this. If you are only storing and retrieving it then this isn't an issue, of course.

if you have 32 bit processor and you will use 16bit value (for memory economy) it will be aligned to 32bit. So I think it is not so important use 16bit uint instead of 32bit value.

Related

How and when to use :short in C#?

I want to know when to use :short in C#?
Please help I want to use it instead of int.
Is using short a good or bad idea?
short - aka Int16 - has some very real but limited uses.
Example scenarios:
when the input value is limited to 16-bits, and you don't want to violate an invariant (perhaps because it maps to a database column that is 16 bits - smallint in SQL Server, for example)
declaring an enum that is : short for similar reasons
because you're implementing an algorithm that demands 16-bit wrapping behaviour - CRC-16, for example
when you are writing a struct with explicit layout that needs to map a very specific configuration (usually related to C/C++ mapping)
It is unusual, but by no means unexpected. Similarly: byte, sbyte, ushort, uint, long, ulong, etc.
int is a great default, but it is by no means the only option.
You will rarely need to use short, and I think it's reasonable to consider its use "bad" unless there's a compelling reason for using it.
int will generally perform better than short on modern CPUs.
For example, you may need to use short in a struct used to interoperate with legacy unmanaged code.
It's more optimal solution for memory saving to use proper type, because short has 16 bits size and int has 32 bits size.

Purpose of casting -1 to uint32?

This is probably a really silly question to experienced C++ developers, but what is the purpose of casting a -1 to uint32? I am translating a program from C++ to C# and there are many occasions when I see something like this:
static const uint32 AllTypes = static_cast<uint32>(-1);
What exactly does this do? How can the same be accomplished in C#?
On systems using two's complement, casting -1 to unsigned gives the highest value an unsigned number can represent.
In C# you can use unchecked((UInt32)-1) or better: UInt32.MaxValue. This is well defined behavior, and works on all CPU architectures.
According to the thread rve linked, casting -1 to unsigned results in all bits being set on all architectures in C++.
How can the same be accomplished in C#
uint AllTypes = uint.MaxValue;
I guess it's used to have all bits to 1. Useful when we use tagged data. Probably each elementary type it's given a bit, and 'complex' types (arrays, for instance) get their own.

The new IntPtr.Add method - am I missing the point of the int?

Starting from FW 4.0, the IntPtr structure has the Add method:
public static IntPtr Add(
IntPtr pointer,
int offset
)
Which is great, as it's supposed to address all those questions on IntPtr math we have had (1, 2, probably more).
But why is the offset int?
Must it not be IntPtr? I can easily imagine offsetting a 64-bit pointer by a value which is beyond the int range.
For instance, consider Marshal.OffsetOf:
public static IntPtr OffsetOf(
Type t,
string fieldName
)
It returns an IntPtr as the offset to the structure member. Which makes perfect sense! And you cannot easily use this offset with the new Add method. You'd have to cast it to Int64, then call Add several times in a loop.
Also, it seems to kill the very idea of the IntPtr.Size being irrelevant to a properly written application. You will have to cast the offset to a particular type, such as Int64, at which point you must start managing the size difference. And image what will happen when 128-bit IntPtr appears.
My question here is, why?
Am I correct in my conclusions, or am I missing the point?
It corresponds to a restriction in the x64 architecture. Relative addressing is limited to a signed 32-bit offset value. Matt Pietrek mentions this in this article (near "Luckily, the answer is no"). This restriction also explains why .NET objects are still limited to 2GB in 64-bit mode. Similarly, in native x64 C/C++ code memory allocations are limited as well. It is not that it is impossible, the displacement could be stored in a 64-bit register, it is just that this would make array indexing a lot more expensive.
The mysterious return type of Marshal.OffsetOf() is probably a corner-case. A managed struct could result in an unmanaged version after applying [StructLayout] and [MarshalAs] that's larger than 2GB.
Yes, this wouldn't map well to some future 128-bit architecture. But it is extraordinarily difficult to prep today's software for an arch when nobody knows what it will look like. Perhaps the old adage fits, 16 Terabytes ought to be enough for anybody. And there's lots of room left to grow beyond that, 2^64 is rather a large number. Current 64-bit processors only implement 2^48. Some seriously non-trivial problems need to be solved before machines can move that close.
If you define only:
public static IntPtr Add(IntPtr pointer, IntPtr offset)
then, adding a 32 bits offset to a 64 bits pointer is less readable, IMHO.
Again, if you define
public static IntPtr Add(IntPtr pointer, long offset)
then, adding a 64 bits offset to a 32 bits pointer is also bad.
By the way, Substract returns an IntPtr, so the IntPtr logic is not broken in anyway.

C# Network encoding

I'm working on a networking application in C#, sending a lot of plain numbers across the network. I discovered the IPAddress.HostToNetworkOrder and IPAddress.NetworkToHostOrder methods, which are very useful, but they left me with a few questions:
I know I need to encode and decode integers, what about unsigned ones? I think yes, so at the moment I'm doing it by casting a pointer to the unsigned int into a pointer to an int, and then doing a network conversion for the int (since there is no method overload that takes unsigned ints)
public static UInt64 HostToNetworkOrder(UInt64 i)
{
Int64 a = *((Int64*)&i);
a = IPAddress.HostToNetworkOrder(a);
return *((UInt64*)&a);
}
public static UInt64 NetworkToHostOrder(UInt64 a)
{
Int64 i = *((Int64*)&a);
i = IPAddress.HostToNetworkOrder(i);
return *((UInt64*)&i);
}
2. What about floating point numbers (single and double). I think no, however If I do need to should I do a similar method to the unsigned ints and cast a single pointer into a int pointer and convert like so?
EDIT:: Jons answer doesn't answer the second half of the question (it doesn't really answer the first either!), I would appreciate someone answering part 2
I suspect you'd find it easier to use my EndianBinaryReader and EndianBinaryWriter in MiscUtil - then you can decide the endianness yourself. Alternatively, for individual values, you can use EndianBitConverter.
You'd better read several RFC documents to see how different TCP/IP protocols (application level, for example, HTTP/FTP/SNMP and so on).
This is generally speaking, a protocol specific question (both your questions), as your packet must encapsulate the integers or floating point number in a protocol defined format.
For SNMP, this is a conversion that changing an integer/float number to a few bytes and changing it back. ASN.1 is used.
http://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One

.NET Integer vs Int16?

I have a questionable coding practice.
When I need to iterate through a small list of items whose count limit is under 32000, I use Int16 for my i variable type instead of Integer. I do this because I assume using the Int16 is more efficient than a full blown Integer.
Am I wrong? Is there no effective performance difference between using an Int16 vs an Integer? Should I stop using Int16 and just stick with Integer for all my counting/iteration needs?
You should almost always use Int32 or Int64 (and, no, you do not get credit by using UInt32 or UInt64) when looping over an array or collection by index.
The most obvious reason that it's less efficient is that all array and collection indexes found in the BCL take Int32s, so an implicit cast is always going to happen in code that tries to use Int16s as an index.
The less-obvious reason (and the reason that arrays take Int32 as an index) is that the CIL specification says that all operation-stack values are either Int32 or Int64. Every time you either load or store a value to any other integer type (Byte, SByte, UInt16, Int16, UInt32, or UInt64), there is an implicit conversion operation involved. Unsigned types have no penalty for loading, but for storing the value, this amounts to a truncation and a possible overflow check. For the signed types every load sign-extends, and every store sign-collapses (and has a possible overflow check).
The place that this is going to hurt you most is the loop itself, not the array accesses. For example take this innocent-looking loop:
for (short i = 0; i < 32000; i++) {
...
}
Looks good, right? Nope! You can basically ignore the initialization (short i = 0) since it only happens once, but the comparison (i<32000) and incrementing (i++) parts happen 32000 times. Here's some pesudo-code for what this thing looks like at the machine level:
Int16 i = 0;
LOOP:
Int32 temp0 = Convert_I16_To_I32(i); // !!!
if (temp0 >= 32000) goto END;
...
Int32 temp1 = Convert_I16_To_I32(i); // !!!
Int32 temp2 = temp1 + 1;
i = Convert_I32_To_I16(temp2); // !!!
goto LOOP;
END:
There are 3 conversions in there that are run 32000 times. And they could have been completely avoided by just using an Int32 or Int64.
Update: As I said in the comment, I have now, in fact written a blog post on this topic, .NET Integral Data Types And You
According to the below reference, the runtime optimizes performance of Int32 and recommends them for counters and other frequently accessed operations.
From the book: MCTS Self-Paced Training Kit (Exam 70-536): Microsoft® .NET Framework 2.0—Application Development Foundation
Chapter 1: "Framework Fundamentals"
Lesson 1: "Using Value Types"
Best Practices: Optimizing performance
with built-in types
The runtime optimizes the performance of 32-bit integer types (Int32 and UInt32), so use those types for counters and other frequently accessed integral variables.
For floating-point operations, Double is the most efficient type because those operations are optimized by hardware.
Also, Table 1-1 in the same section lists recommended uses for each type.
Relevant to this discussion:
Int16 - Interoperation and other specialized uses
Int32 - Whole numbers and counters
Int64 - Large whole numbers
Int16 may actually be less efficient because the x86 instructions for word access take up more space than the instructions for dword access. It will depend on what the JIT does. But no matter what, it's almost certainly not more efficient when used as the variable in an iteration.
The opposite is true.
32 (or 64) bit integers are faster than int16. In general the native datatype is the fastest one.
Int16 are nice if you want to make your data-structures as lean as possible. This saves space and may improve performance.
Never assume efficiency.
What is or isn't more efficient will vary from compiler to compiler and platform to platform. Unless you actually tested this, there is no way to tell whether int16 or int is more efficient.
I would just stick with ints unless you come across a proven performance problem that using int16 fixes.
Any performance difference is going to be so tiny on modern hardware that for all intents and purposes it'll make no difference. Try writing a couple of test harnesses and run them both a few hundred times, take the average loop completion times, and you'll see what I mean.
It might make sense from a storage perspective if you have very limited resources - embedded systems with a tiny stack, wire protocols designed for slow networks (e.g. GPRS etc), and so on.
Use Int32 on 32-bit machines (or Int64 on 64-bit machines) for fastest performance. Use a smaller integer type if you're really concerned about the space it takes up (may be slower, though).
The others here are correct, only use less than Int32 (for 32-bit code)/Int64 (for 64-bit code) if you need it for extreme storage requirements, or for another level of enforcement on a business object field (you should still have propery level validation in this case, of course).
And in general, don't worry about efficiency until there is a performance problem. And in that case, profile it. And if guess & checking with both ways while profiling doesn't help you enough, check the IL code.
Good question though. You're learning more about how the compiler does it's thing. If you want to learn to program more efficiently, learning the basics of IL and how the C#/VB compilers do their job would be a great idea.
I can't imagine there being any significant performance gain on Int16 vs. int.
You save some bits in the variable declaration.
And definitely not worth the hassle when the specs change and whatever you are counting can go above 32767 now and you discover that when your application starts throwing exceptions...
There is no significant performance gain in using a data type smaller than Int32, in fact, i read somewhere that using Int32 will be faster than Int16 because of memory allocation

Categories