-1
\$\begingroup\$

This is my first code review question in here, so kindly guide me if I need to format the question in a better way.

Task Description

Aim of the task is to create a set of methods that would allow me to create random values for given primitive types. This would be used later in a method that would reflect on a class/struct and assign random values to each of the members (nested properties are also taken care of in the other method).

The code attached set of methods for creating random values. I was wondering if this is the best way to create a random value for each of the primitive type.

Code

private static bool RandomBoolean()
{
    return Convert.ToBoolean(random.Next(0, 2)); 
}
private static double RandomDouble(Int32 minValue=Int32.MinValue,Int32 maxValue= Int32.MaxValue)
{
    return random.NextDouble() * (double)random.Next(minValue,maxValue);
}

private static char RandomChar(bool isLowerCase = true)
{
    if (isLowerCase)
        return  (char)random.Next((int)'a', ((int)'z')+1);
     else
        return (char)random.Next((int)'A', ((int)'Z')+1);
}
private static byte RandomByte()
{
    var byteArray = new byte[1];
    random.NextBytes(byteArray);
    return byteArray[0];
}

private static sbyte RandomSByte(int minValue=sbyte.MinValue, int maxValue = sbyte.MaxValue)
{
    return (sbyte)random.Next(minValue, maxValue);
}

private static float RandomFloat()
{
    double mantissa = (random.NextDouble() * 2.0) - 1.0;
    double exponent = Math.Pow(2.0, random.Next(-126, 128));
    return (float)(mantissa * exponent);
}


private static decimal RandomDecimal()
{
    byte scale = (byte)random.Next(29);
    bool sign = random.Next(2) == 1;
    return new decimal(random.NextInt32(),
                       random.NextInt32(),
                       random.NextInt32(),
                       sign,
                       scale);
}

private static short RandomInt16(int minValue = Int16.MinValue, int maxValue = Int16.MaxValue)
{
    return (short)random.Next(minValue, maxValue);
}

private static int RandomInt32(int minValue = Int32.MinValue, int maxValue = Int32.MaxValue)
{
    return random.Next(minValue, maxValue);
}

private static long RandomInt64(long minValue = Int32.MinValue, long maxValue = Int32.MaxValue)
{
    long result = random.Next((Int32)(minValue >> 32), (Int32)(maxValue >> 32));
    result = (result << 32);
    result = result | (long)random.Next((Int32)minValue, (Int32)maxValue);
    return result;
}


private static UInt16 RandomUInt16()
{
    var byteArray = new byte[2];
    random.NextBytes(byteArray);
    return BitConverter.ToUInt16(byteArray, 0);
}

private static UInt32 RandomUInt32()
{
    var byteArray = new byte[4];
    random.NextBytes(byteArray);
    return BitConverter.ToUInt32(byteArray,0);
}

private static UInt64 RandomUInt64()
{
    var byteArray = new byte[8];
    random.NextBytes(byteArray);
    return BitConverter.ToUInt64(byteArray, 0);
}

private static string RandomString(int length = 10)
{
    const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    return new string(Enumerable.Repeat(chars, length)
      .Select(s => s[random.Next(s.Length)]).ToArray());
}

Each of the methods are private and static by intention. I have a extension method GetRandomValues(this Type source) defined in the same class which has a return type dynamic.

The given methods are part of a solution which aims to create/fill collections of any type T. The solution would reflect over the properties in T (nested properties as well), and assign random values to each of them. For example, if the user had a Student class with properties Name and Age, the utility method would create a collection objects, with random values assigned to each property of Student (for each instance in the collection).

This becomes useful when testing (for example) a LINQ query on a collection, making it better than manually creating the collection.

\$\endgroup\$

closed as off-topic by t3chb0t, Graipher, Mast, Raystafarian, Ludisposed Jan 8 at 12:27

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Lacks concrete context: Code Review requires concrete code from a project, with sufficient context for reviewers to understand how that code is used. Pseudocode, stub code, hypothetical code, obfuscated code, and generic best practices are outside the scope of this site." – t3chb0t, Graipher, Mast, Raystafarian, Ludisposed
If this question can be reworded to fit the rules in the help center, please edit the question.

  • 1
    \$\begingroup\$ What is the intented use-case for these random values? Fuzz-testing? And why would the return type of GetRandomValues need to be dynamic (instead of object)? \$\endgroup\$ – Pieter Witvoet Jan 2 at 0:42
  • \$\begingroup\$ @PieterWitvoet The intended use-case is to create a Collection Generator for any given Type. Say you have a class named XYZ, it should generate a collection of XYZ with random values assigned to members. Regarding dynamic/object => , any particular merits/demerits of either in above scenario ? \$\endgroup\$ – Anu Viswan Jan 2 at 0:49
  • 1
    \$\begingroup\$ And what's the use-case for those random-value collections? - Regarding dynamic, it involves late binding, which means more work at run-time and a loss of compile-time error detection, so I wouldn't use it unless I had a good reason. \$\endgroup\$ – Pieter Witvoet Jan 2 at 2:35
  • 2
    \$\begingroup\$ Please post the entire class, without removing anything, we need the public method(s) becuase there is no point in reviewing private APIs that aren't used anywhere. \$\endgroup\$ – t3chb0t Jan 3 at 7:43
  • 1
    \$\begingroup\$ @AnuViswan: are you sure that 'totally' random values are useful, or do the tests require more specific randomized values? Something like Enumerable.Range(0, 100).Select(i => new Student { Name = $"NAME {i}", Age = random.Next(20, 50) }).ToArray(); doesn't take too much effor, but gives you much more control over the actual values, how your solution compare to that? \$\endgroup\$ – Pieter Witvoet Jan 3 at 17:45
4
\$\begingroup\$

One problem with your code would be the distribution of values for some of the functions that might not match the expected distribution (usually linear) or might not even be inside the specified range.

One example would be RandomDouble with arguments 10 and 20. You would multiply a number between 0.0 and 1.0 with a number between 10 and 20. In that case, most of the returned number would be below 10.0 and you would have an higher probability to get a number between 10 and 11 than a number between 19 and 20.

For RandomChar often, you would probably want a mix of uppercase and lowercase with possibly numbers and punctuation (think a password) so as written, the function might often be almost useless.

RandowInt64 will also not properly respect the specified range. Some values would never be returned and you probably also could have some out of range values. In particular, you cannot simply join two 32 bit numbers like that if the range can include negative values.

Another thing that is strange is that for some types, you assume that you always want the whole range while for other types, you ask the user for the range.

It is also weird that the default range for an Int64 is the range of an Int32.

\$\endgroup\$
  • \$\begingroup\$ Thank you for the feedback, I will take note of each point you mentioned. \$\endgroup\$ – Anu Viswan Jan 4 at 1:24

Not the answer you're looking for? Browse other questions tagged or ask your own question.