this post was submitted on 11 Jul 2024
5 points (100.0% liked)

C Sharp

1532 readers
2 users here now

A community about the C# programming language

Getting started

Useful resources

IDEs and code editors

Tools

Rules

Related communities

founded 1 year ago
MODERATORS
 

Let's say I have a method that I want to make generic, and so far it had a big switch case of types.

For an simplified example,

switch (field.GetType()) {
case Type.Int: Method((int)x)...
case Type.NullInt: Method((int?)x)...
case Type.Long: Method((long)x)...

I'd like to be able to just call my GenericMethod(field) instead and I'm wondering if this is possible and how would I go around doing it.

GenericMethod(field)

public void GenericMethod<T>(T field)

Can I use reflection to get a type and the pass it into the generic method somehow, is it possible to transform Type into ?

Can I have a method on the field object that will somehow give me a type for use in my generic method?

Sorry for a confusing question, I'm not really sure how to phrase it correctly, but basically I want to get rid of switch cases and lots of manual coding when all I need is just the type (but that type can't be passed as generic from parent class)

you are viewing a single comment's thread
view the rest of the comments
[–] DrDeadCrash 1 points 4 months ago

Here's a real world side project example of how I handle this situation:

 public IResult<T> GetResourceValue<T>(string path)
    {
        string err = $"{typeof(T).FullName} is not available from this Resource ({nameof(FileSystemResource)})";

        switch (typeof(T))
        {
            case Type t when t == typeof(DriveInfo):
                return (IResult<T>)new Ok<DriveInfo>(BackingValue);
            case Type t when t == typeof(DirectoryInfo):
                err = $"Directory path invalid: {path}";
                var dir = new DirectoryInfo(path);

                if (dir.Exists)
                    return (IResult<T>)new Ok<DirectoryInfo>(dir);
                break;
            case Type t when t == typeof(FileInfo):
                err = $"File path invalid: {path}";
                var file = new FileInfo(path);

                if (file.Exists)
                    return (IResult<T>)new Ok<FileInfo>(file);
                break;
        }
        return new Error<T>(err);
    }

You said elsewhere that it feels like you're doing something wrong if you have to check for every type just to use a Generic. I think you're right in thinking along those lines. There should be a minimal number of types to check, and Ideally limited via a type constraint.

Here's example that includes a constraint:

    public IResult<T> GetValue<T>() where T : struct =>
        typeof(T) switch
        {
            Type t when t == typeof(int) && value <= int.MaxValue =>
             (IResult<T>)new Ok<int>((int)value),
            Type t when t == typeof(uint) && value <= uint.MaxValue && value >= uint.MinValue =>
             (IResult<T>)new Ok<uint>((uint)value),
            Type t when t == typeof(byte) && value <= byte.MaxValue && value >= byte.MinValue =>
             (IResult<T>)new Ok<byte>((byte)value),
            Type t when t == typeof(sbyte) && value <= (int)sbyte.MaxValue =>
             (IResult<T>)new Ok<sbyte>((sbyte)value),
            Type t when t == typeof(short) && value <= (int)short.MaxValue =>
             (IResult<T>)new Ok<short>((short)value),
            Type t when t == typeof(ushort) && value <= ushort.MaxValue =>
             (IResult<T>)new Ok<ushort>((ushort)value),
            Type t when t == typeof(long) && value <= long.MaxValue =>
             (IResult<T>)new Ok<long>((long)value),
            Type t when t == typeof(ulong) => (IResult<T>)new Ok<int>((int)value),
            _ => new IntegerError<T>()
        };