Value Types



  • C# has a Type parameter feature, such that a function / class can be used with different types of a variable at run-time. Jonny found a very intelligent use of it:

    T value1 = (T)Convert.ChangeType(cameraParameterValue, typeof(T));
    T value2 = (T)Convert.ChangeType(_value, typeof(T));
    
    if ((value1 is double || value1 is float) && (value2 is double || value2 is float))
    {
        if (Math.Abs((double)Convert.ChangeType(value1, typeof(double)) - (double)Convert.ChangeType(value2, typeof(double))) < 0.001)
    

    As you can see, there is exactly one (i.e. 1) type parameter T. That is, when both calls to (T)Convert.ChangeType have succeeded, both value1 and value2 have the same type.

    Now look at the first if clause: do you really need to check value2?

    The second if clause with its extra manual conversion to double is NOT a WTF by Jonny, but of C#. You cannot simply do
    if (Math.Abs(value1 - value2) < 0.001)
    or
    if (Math.Abs((double)value1 - (double)value2) < 0.001)
    because C# fails to see the types.
    :wtf_owl:


  • Notification Spam Recipient

    @BernieTheBernie said in Value Types:

    because C# fails to see the types.

    No no, it fails to implicitly convert a Type into a particular object of type Type with the value of T. There's a difference.

    Edit: 🚎 if you think I'm serious.


  • Considered Harmful

    ChangeType returns object, boxing your numeric types. That's why C# needs to be told to unbox it back to double when you want to use it as such. The whole deal is unwieldy, but that's why you don't screw around with types this way. The whole snippet is one big is :wtf_owl: .



  • I don't get it. Why in the world would you need T when at the end of it, you are just going to perform double-type operations?



  • @BernieTheBernie said in Value Types:

    C# has a Type parameter feature, such that a function / class can be used with different types of a variable at run-time. Jonny found a very intelligent use of it:

    T value1 = (T)Convert.ChangeType(cameraParameterValue, typeof(T));
    T value2 = (T)Convert.ChangeType(_value, typeof(T));
    
    if ((value1 is double || value1 is float) && (value2 is double || value2 is float))
    {
        if (Math.Abs((double)Convert.ChangeType(value1, typeof(double)) - (double)Convert.ChangeType(value2, typeof(double))) < 0.001)
    

    As you can see, there is exactly one (i.e. 1) type parameter T. That is, when both calls to (T)Convert.ChangeType have succeeded, both value1 and value2 have the same type.

    Now look at the first if clause: do you really need to check value2?

    The second if clause with its extra manual conversion to double is NOT a WTF by Jonny, but of C#. You cannot simply do
    if (Math.Abs(value1 - value2) < 0.001)
    or
    if (Math.Abs((double)value1 - (double)value2) < 0.001)
    because C# fails to see the types.
    :wtf_owl:

    try:

                var value1 = cameraParameterValue as double?;
                var value2 = _value as double?;
    
                if (value1.HasValue && value2.HasValue)
                {
                    if (Math.Abs(value1.Value - value2.Value) < 0.001)
                    {
                        // Rest of code
                    }
                }
    

    It compiles, and inspection indicates that it is functionally equivalent to the version you provided (assuming that there is not some weird incompatibility with Conver.ChangeType that differs from the as keyword.... which honestly i havent found one yet.

    I omitted the float check because well, that has an implicit conversion to double so floatvalue as double? just upcasts the float to the double and now i don't have to worry about it.



  • @Vixen Beyond this comparison for floating point values with a delta, there are other equality comparisons for non-floating values, too. So that's not the solution to the whole issue.

    Just had fun with this block of code because of the unnecessary double-check in the first if-clause, plus the .Net convolution there after.



  • @BernieTheBernie said in Value Types:

    there are other equality comparisons for non-floating values,

    well if yah'dve mentioned that earlier maybe we wouldn't be in this mess, now would we?

    -tries to glare convincinly angrily at @BernieTheBernie, critical fails and just looks silly instead-



  • Now look at the first if clause: do you really need to check value2?

    Wait, do you think that if you have two variables both with generic type T, and you've determined that one of them is Foo, the compiler should be able to infer that the other also definitely is Foo?

    It can't do that, because that's not actually true!

    using System;
    
    interface Bla {}
    
    class Wibble : Bla {}
    class Wobble : Bla {}
    
    public class Program {
    	static public void Main() {
    		Bla arg1 = new Wibble();
    		Bla arg2 = new Wobble();
    		GenericMethod(arg1, arg2);
    	}
    
    	static public void GenericMethod<T>(T arg1, T arg2) {
    		if (arg1 is Wibble) Console.WriteLine("arg1 is Wibble");
    		if (!(arg2 is Wibble)) Console.WriteLine("But arg2 is not Wibble!");
    	}
    }
    

    The use of the word "the" here...

    both value1 and value2 have the same type.

    ... seems like it captures the root of the fallacy. If "types" include interfaces or superclasses, then it's somewhat unsafe to talk about "the" type of an object, since an object can then have many types. Knowing the type of a variable it was assigned, or knowing a type for which an is check returned true, thus generally gives you only partial information about which concrete type the object has.


  • BINNED

    I have this weird feeling that the whole interface of whatever this is is horribly misdesigned, and the snippet in question is just a result of it.



  • @Cabbage The code snippet above is a verbatim copy, no line or function call in between left out. So, both value1 and value2 have the same type T. In this simple scenario, it is sufficient to check one value only.



  • @BernieTheBernie said in Value Types:

    @Cabbage The code snippet above is a verbatim copy, no line or function call in between left out. So, both value1 and value2 have the same type T. In this simple scenario, it is sufficient to check one value only.

    Without seeing the declarations of cameraParameterValue and _value, which your snippet does not supply, it is impossible to make that determination.


  • Java Dev

    @BernieTheBernie said in Value Types:

    @Cabbage The code snippet above is a verbatim copy, no line or function call in between left out. So, both value1 and value2 have the same type T. In this simple scenario, it is sufficient to check one value only.

    As I read it, they have both been confirmed to be of some type which inherits from T. I do not know what the hierarchy leading to double is, or even whether C# uses the single tree or the forest paradigm here. Could it be that T is Object, cameraParameterValue is double, and _value is String?



  • @TheCPUWizard said in Value Types:

    @BernieTheBernie said in Value Types:

    @Cabbage The code snippet above is a verbatim copy, no line or function call in between left out. So, both value1 and value2 have the same type T. In this simple scenario, it is sufficient to check one value only.

    Without seeing the declarations of cameraParameterValue and _value, which your snippet does not supply, it is impossible to make that determination.

    it is however sufficient to determine that the larger code from which this is snipped was spawned in the fetid mind of the elder god of chaos and discord, whose name we must not speak lest we summon them back to this plane to rend our minds and this world asunder.


  • Trolleybus Mechanic

    @Vixen I don't remember @blakeyrat being this powerful.



  • @Mingan said in Value Types:

    @Vixen I don't remember @blakeyrat being this powerful.

    he got better


  • Notification Spam Recipient

    @Vixen said in Value Types:

    -tries to glare convincinly angrily at @BernieTheBernie, critical fails and just looks silly instead-

    *boops the silly looking Vixen* don't mind the Bernie, he's just providing irrelevant context and laying down extra tracks to enhance derailment opportunities.



  • @Vixen said in Value Types:

    he got better

    20b055c1-de01-4ad2-b171-b1994b7572ff-image.png



  • @Tsaukpaetra said in Value Types:

    @Vixen said in Value Types:

    -tries to glare convincinly angrily at @BernieTheBernie, critical fails and just looks silly instead-

    *boops the silly looking Vixen* don't mind the Bernie, he's just providing irrelevant context and laying down extra tracks to enhance derailment opportunities.

    54a84392-6735-4251-9e4a-7a75dd4060ef-image.png



  • @BernieTheBernie said in Value Types:

    @Cabbage The code snippet above is a verbatim copy, no line or function call in between left out. So, both value1 and value2 have the same type T. In this simple scenario, it is sufficient to check one value only.

    Just to be clear, double has 8 types in its inheritance tree: 3 classes (including itself) and 5 interfaces. Just because value1 and value2 have the same type T does not mean that T is double.



  • @powerlord said in Value Types:

    @BernieTheBernie said in Value Types:

    @Cabbage The code snippet above is a verbatim copy, no line or function call in between left out. So, both value1 and value2 have the same type T. In this simple scenario, it is sufficient to check one value only.

    Just to be clear, double has 8 types in its inheritance tree: 3 classes (including itself) and 5 interfaces. Just because value1 and value2 have the same type T does not mean that T is double.

    nor does it mean that they are actually the same type, let alone actually Type T. They both are Type T, but one or both may derive from subclasses of T

    in example

    class Animal {
    }
    class Mammal : Animal {
    }
    class Homonid: Mammal {
    }
    class Canid: Mammal {
    }
    class Human: Homonid {
    }
    class Fox: Canid {
    }
    class Powerlord: Human {
    }
    class Vixen: Fox {
    }
    
    static class Main {
        public static void Main() {
            Human powerlord = new Powerlord();
            Fox vixen = new Vixen();
            Animal offspring = BeastWithTwoBacks<Animal>(powerlord, vixen)
        }
        
            static T BeastWithTwoBacks<T>(T left, T, right) { // Footnote 1
        
                /// left and right both derive from T but are not necessarily T
        
            }
    

    1- Yes that was an excuse to make a sex joke



  • You can't derive from a double, nor can there be a T such that Convert.ChangeType results in a value that is a double. Well, of course, except when T is object, and the input value was a double to begin with (because if the target type is object it just returns the input value). So actually the original snippet was right(ish).
    Although I would rather just test typeof(T)==typeof(double) || typeof(T)==typeof(float), that's enough for this snippet, as far as I can tell.


Log in to reply