简体   繁体   中英

Will work these code the same (Generic Class with base class constraint vs Non-generic Class “counterpart”)

I'm testing the implementation of IComparer interface for my class Inventory. I have two versions of it realization, will it works the same? (Question 1)

class Inventory
{
    public string name;
    double cost;
    int onhand;
    public Inventory(string n, double c, int h)
    { //...    }
    }
}
class CustomInvComparer : IComparer<Inventory>
    {
        public int Compare(Inventory x, Inventory y)
        {
            return string.Compare(x.name, y.name, StringComparison.Ordinal);
        }
    }
class CompInv<T> : IComparer<T> where T : Inventory
    {
        public int Compare(T x, T y)
        {
            return string.Compare(x.name, y.name, StringComparison.Ordinal);
        }
    }

And why, in cases of implementation the IComparer interface for int32 and for string, doesn't work the "second variants" (w/o comment will be main error CS0701). I know that the "second variants" (commented) are incorrect from the point of view of syntax "Constraints on type parameters (C# Programming Guide)", but I doesn't see logical difference with foregoing variant "where T : Inventory"? (Question 2)

    class CustomStringComparer : IComparer<System.String>
{
    public int Compare(System.String x, System.String y)
    {
        return x.CompareTo(y);
    }
}

//class CompStr<T> : IComparer<T> where T : System.String
//{
//    public int Compare(T x, T y)
//    {
//        return string.Compare(x, y, StringComparison.Ordinal);
//    }
//}

class CustomIntComparer : IComparer<System.Int32>
{
    public int Compare(System.Int32 x, System.Int32 y)
    {
        return x.CompareTo(y);
    }
}

//class CompStr<T> : IComparer<T> where T : System.Int32
//    {
//    public int Compare(T x, T y)
//    {
//        return string.Compare(x, y, StringComparison.Ordinal);
//    }
//}

I have two versions of it realization, will it works the same? (Question 1)

Your two IComparer<T> implementations have exactly the same logic, so in that sense they will work exactly the same. The only material difference is that the generic version will work not just to compare for types of Inventory , but any subclass of Inventory as well.

Since via type parameter variance in generic interfaces, you can use the non-generic version with scenarios where an Inventory subclass is being used, this difference doesn't have much practical importance. You should be able to use either in exactly the same situations.

As far as your second question goes:

And why, in cases of implementation the IComparer interface for int32 and for string, doesn't work the "second variants" (w/o comment will be main error CS0701)

The answer to that is right in the error message :

A type used as a constraint must be an interface, a non-sealed class or a type parameter.

System.String is a sealed class, and System.Int32 isn't a class at all. Neither are either of those an interface or type parameter. So neither qualifies as a constraint.

More practically speaking: the reason sealed classes and value types (structs, ie something like System.Int32 ) are not valid constraints is that they wouldn't make any sense as a constraint. The constraint allows the type parameter to be a type that inherits the constraint type. But sealed classes and value types can't have inherited types. So using them as a constraint would provide zero benefit. In such situations, you'd do just as well to omit the type parameter and use that type explicitly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM