locked
function that returns the default value of any variable (Various problems). RRS feed

  • Question

  • I have a function that has the goal of returning the default value of any variable. Therefore, a dynamic parameter receives the input variable. I have reproduced here in the simplest way the problems found.

    Problem 1: You cannot return the Default of a nullable variable. Apparently, when a nullable variable is passed to a function that receives it with a dynamic parameter, boxing occurs and the nullable property is lost. Ridiculous?
    dynamic MyOrigen;
    bool? MyVariable = false;
    MyOrigen = MyVariable;

    System.Type MyType = MyOrigen.GetType();
    System.Type MyType_Nullable_GetUnderlyingType = System.Nullable.GetUnderlyingType(MyType);
    bool MyType_EsNullable = (MyType_Nullable_GetUnderlyingType != null);  // FAILS. Always returns false.

    Problem 2: Trying to instantiate a string fails.
    string MyVariable   = "AA";
    System.Type MyType  = MyVariable.GetType();
    dynamic MyInstancia = System.Activator.CreateInstance(MyType); // ERROR. {"There is no parameterless constructor defined for this object."} -2146233069

    Problem 3: Error when trying to retrieve the GetType of a variable that has a null value.

    How can I know if a dynamic is null or contains a variable that has a null value?

    If the dynamic contains a variable, I want to know its type even if it has a null value.
    dynamic MyOrigen;
    string MyVariable = null;
    MyOrigen = MyVariable;
    System.Type MyType  = MyOrigen.GetType(); // ERROR. Unable to bind at runtime on a NULL reference..

    Problem 4: (Same as 3 but more simple). Error when trying to retrieve the GetType of a variable that has a null value.
    string MyVariable  = null;
    System.Type MyType = MyVariable.GetType(); // ERROR. Object reference not set to an instance of an object.


    • Edited by zequion1 Thursday, July 23, 2020 4:57 AM
    Thursday, July 23, 2020 4:56 AM

All replies

  • Hi zequion1,
    For question one:
    About Nullable.GetUnderlyingType(Type) method, the parameters passed in should be a closed generic nullable type. If not, it will return null.
    When you call GetType method, it will return System.Boolean instead of System.Nullable`1[System.Boolean], and you can use typeof(bool?).
    More details you can refer to this thread.
    For question two:
    String classes are immutable. You can not change it after you create it, and this explains why it has no parameterless constructor.
    Please refer to Hans Passant answer.
    You can also try the following code:

    var ss=System.Reflection.Assembly.GetExecutingAssembly().CreateInstance(MyVariable);

    For question three:
    Null is a special value contained in the domain of any reference type. It basically determines that there is no valid reference. So when the value is null, the type can not be specified.
    You can get type of a nullable type when the underlying value is null by following code example:

    static void Main(string[] args)
    {
        decimal? x = null;
        Type xType = GetObjectType(() => x);
        Type genericTypeArgument = GetObjectType(() => x).GetGenericArguments()[0];
        Console.WriteLine(genericTypeArgument);
    }
    public static Type GetObjectType(Expression<Func<object>> expr)
    {
        var obj = ((UnaryExpression)expr.Body).Operand;
        return (Type)((PropertyInfo)obj.GetType()
            .GetProperty("Type", BindingFlags.Instance | BindingFlags.Public)).GetValue(obj);
    }

    Here is a similar thread you can refer to.
    For question four:
    Please refer to Marcus Griep answer.
    Best Regards,
    Daniel Zhang


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Thursday, July 23, 2020 8:59 AM
  • I appreciate you looking at it and responding but you are only confirming the limitations of c# for me and nothing has been resolved.

    I answer your answer to Problem 1:
    I can't use typeof (bool?) Because the function requires to return the default of any type of variable because I have other functions that depend on it. So I cannot use a known type. What if I already know bool? Why am I going to ask if it is nullable?

    I respond to your answer to Problem 2:
    It does not solve anything that in your example an object is returned as default (string).

    I respond to your answer to Problem 3:
    If at the end of these lines, I stop the execution and use the Debug to query "MyOrigen" correctly indicates that it is a dynamic that contains a string that has a null value. How is it done with code?

    dynamic MyOrigen;
    string MyVariable = null;
    MyOrigen = MyVariable;

    I cannot instantiate a string, I cannot know which variables are nullable, I cannot know the type of a variable with null value. And there's more, this is just the beginning ... (to be continued).


    • Edited by zequion1 Thursday, July 23, 2020 10:49 AM
    Thursday, July 23, 2020 10:44 AM
  • I have created this function to try to get out of trouble as best as possible.

    If you can think how to improve it, I encourage you to do it. // -------------------------------------------------- // CREATEINSTANCE. NO ES ARRAY. // Origen, dynamic/System.Type // -------------------------------------------------- // [System.Diagnostics.DebuggerStepThroughAttribute] internal static dynamic Fcn_CreateInstance_No_Array(dynamic Origen, System.Object[] Argumentos = null, dynamic Params = null) { dynamic MyInstancia = null; try { // Comprobaciones. if (Origen == null) return MyInstancia; // Origen_Type. Recupera el TypeOf de la Variable. System.Type Origen_Type = Origen.GetType(); if (Origen_Type == null) return MyInstancia; // ------------------------------ // CREATEINSTANCE. SIN ARGUMENTOS. // ------------------------------ if (Argumentos == null) { // Activator.CreateInstance. try{ MyInstancia = System.Activator.CreateInstance(Origen_Type); } catch (System.Exception ErrorExcp) { // GetExecutingAssembly().CreateInstance. try{ MyInstancia = System.Reflection.Assembly.GetExecutingAssembly().CreateInstance(Origen); } catch(System.Exception ErrorExcp1){} } } // ------------------------------ // CREATEINSTANCE. CON ARGUMENTOS. // ------------------------------ if (Argumentos != null) { // Activator.CreateInstance. try{ MyInstancia = System.Activator.CreateInstance(Origen_Type, Argumentos); } catch (System.Exception ErrorExcp) { bool ignoreCase = true; System.Reflection.BindingFlags MyBindingFlags = System.Reflection.BindingFlags.Default; System.Reflection.Binder MyBinder = null; System.Globalization.CultureInfo MyCultureInfo = null; object[] activationAttributes = null; // GetExecutingAssembly().CreateInstance. try{ MyInstancia = System.Reflection.Assembly.GetExecutingAssembly().CreateInstance(Origen, ignoreCase, MyBindingFlags, MyBinder, Argumentos, MyCultureInfo, activationAttributes); } catch(System.Exception ErrorExcp1){} } } } catch (System.Exception ErrorExcp){ Name_ErrorAdd.Cls_ErrorAdd.Fcn_Error(System.Reflection.MethodBase.GetCurrentMethod(), null, ErrorExcp); } return MyInstancia; }




    • Edited by zequion1 Thursday, July 23, 2020 11:45 AM
    Thursday, July 23, 2020 11:44 AM
  • Hi, 

    lets see it from another perspective, lets code a generic extension method that will return the default type of the caller type, and since this is a generic method we can test different type cases based on T type independently from the value "null case", lets take a look to the code snippet:

    public static class ObjectExtensions
    {
        public static T GetDefault<T>(this T value)
        {
            if(typeof(T).IsAssignableFrom(IEnumerable)) 
            {            
               // manage IEnumerable type case
            }
            return default(T);
        }
    }

    Point? point = null;
    var _defaultPoint = point.GetDefault();
    
    var serializedPoint = JsonConvert.SerializeObject(point);
    var _defaultSerialized = serializedPoint.GetDefault();
    
    string test_str = null;
    test_str = $"{test_str.GetDefault()}";
    Console.WriteLine($"default empty string: {test_str}");
    
    dynamic _dynamic = new { test_value = test_str };
    
    var _defaultDynamic = ObjectExtensions.GetDefault(_dynamic);

    the trick is that the T parameter is always inferred and you can act based on its type. 

    Best regards,

    Mouad.



    Thursday, July 23, 2020 12:18 PM
  • I already have a function based on <T> and there are no problems and json is for web.
    Thursday, July 23, 2020 12:32 PM
  • The answer to problem 2 has helped me because it complements what I already had, as you can see in the function below.
    Thursday, July 23, 2020 12:33 PM
  • hmm, just look at the LINQ implementation of FirstOrDefault().
    Thursday, July 23, 2020 12:41 PM
  • My Claiming Banner: Sql Server TSql in Spanish and Catalan is a Fraud.

    I am the uncle who has spent years trying to get Microsoft to Fix the Serious flaws of Sql Server TSql in Spanish and Catalan. But even though I managed to have them attend to me after two years, soon after they no longer respond (and the failures continue as if nothing).

    Thursday, July 23, 2020 1:02 PM
  • I'm confused as to the purpose of your post. Are you trying to confirm that you cannot do something in C# or something else?

    The fact you're using dynamic is the root of your problems to me. You're trying to do something with dynamic that isn't what it was designed for. As mentioned earlier the correct solution is generics. With generics you can get the default of the type with a single line of code. Generics are almost always the correct solution. When generics don't work you step back to object. You take a hit for boxing but you're going to have that with dynamic anyway. The only issue you'll run into is if you try to modify the value of the boxed object but you shouldn't be doing that anyway. You should return modified values as the return type so boxing issues go away. Dynamic is reserved for when you need to be able to modify the available members of an object which is a boundary case.

    As for C# not having a feature you want, this is true of every language ever written. There is no language that supports all the features you may want. That is the benefit of .NET. You should writing your code in the language that has the features you need for the problem you're trying to solve. Need flexible objects use F#. Need more dynamic runtime binding, consider VB. Use C# for what it is designed for strongly typed OOP code. So if this particular functionality is easier in, say, F# then use that language instead.

    Finally, your comment about JSON being for the web is incorrect. JSON is the defacto data transfer language of modern code (replacing XML). It is used when we need to move data from point A to point B and we cannot use our existing in-memory structures. The web is only one example. We can also use it for database calls and for storing data when we want it to be readable. Take a look at most modern apps and they are using JSON files for their data. While I don't believe that JSON will help with the problem you're trying to solve it definitely isn't for the web only.


    Michael Taylor http://www.michaeltaylorp3.net

    Thursday, July 23, 2020 1:53 PM
  • Microsoft is used to doing basic functions that use <T> types and that's where it ends. It is the programmer who has to perform more extensive functions that are made up of typed functions. But the problem occurs when standard functions are performed that must be used for the use of various types of variables, when its origin type is no longer known. It happens that different types of variables from different parts of the program call one function, another and another, and in the end they end up as a dynamic / object parameter in a standard function. And at that point, nobody remembers the <T> type of the original variable anymore.

    You can't make a program, made up of hundreds of functions, some for <int> others for <string>, some for <T> when Microsoft doesn't have a function that returns <T> of a variable and you can 't do T = typeof (variable) Ridiculous? Yes it is. There will be technical reasons, but it's another big limitation of the c # language.

    As an example, I have tested the "Type Inference" and abandoned it because I found a bug that does not make it feasible.

    The issue is not that there are many failures and limitations, the issue is that the years go by and they do not fix them.

    If I tell Microsoft for years that Sql Server for the Spanish and Catalan language is a FRAUD, and I show it, and having a ticket to attend to me, do you know what Microsoft has been doing since 2008, since it doesn't work the product? DO NOT FIX IT AND DO NOT RESPOND TO MY EMAILS. This is Microsoft's policy.
    Thursday, July 23, 2020 2:31 PM
  • "As an example, I have tested the "Type Inference" and abandoned it because I found a bug that does not make it feasible."

    Please provide a code example of where type inferencing is wrong and you cannot find a solution for it. While there are bugs in it (all compilers have them even C++ after 40 years) many are fixed with newer releases if they are reported. If you have the Github issue where you reported it then we can better understand the issue.

    "Microsoft doesn't have a function that returns <T> of a variable and you can 't do T = typeof (variable) Ridiculous? Yes"

    Agreed that you cannot do that because T is a compile time thing and an instance is a runtime thing. But then again I don't know a single language that could. Do you have a language that could possibly do this? I'm not even sure of the rationale about why this would be useful. The only way to know the type of an instance is to get it at runtime which is long after generics/templates are gone. But if you needed the type then you'd just return Type instead.

    As for the default discussion of earlier, this is a problem in many languages. Outside of an interpreted language I'm not aware of any that can give you the "default value" of a type at runtime (ignoring the fact that 0 is always the default). Default values (more specifically null) are so painful that some languages do away with them altogether. C#, in fact, has started moving away from null. Many in the industry are moving toward "empty objects" in lieu of null (or type defaults). This is more discoverable and easier to code against.


    Michael Taylor http://www.michaeltaylorp3.net

    Thursday, July 23, 2020 5:08 PM
  • Hi

     System.Type MyType = MyOrigen.GetType();
                Type typeOfA = MyType.GetType();
                bool MyType_EsNull = (typeOfA != null);

    Thanks and regards

    Thursday, July 23, 2020 5:34 PM