Home > database >  A class with two types and a single get
A class with two types and a single get

Time:10-08

Let's say I have a class A that has two constructors, one for float and another one for double. It also has a single method that can return either, depending on the type argument.

This is my attempt.

public class A {
    private readonly float fooV1;
    private readonly double fooV2;

    public A(float foo) { this.fooV1 = foo; }
    public A(double foo) { this.fooV2 = foo; }

    public T GetFoo<T>() {
        if (typeof(T) == typeof(float)) { return (dynamic)this.fooV1; }
        if (typeof(T) == typeof(double)) { return (dynamic)this.fooV2; }
        throw new ArgumentException();
    }
}

First of all, this isn't type safe, so it ends up crashing when I call the wrong type. Additionally, I have to cast to dynamic since I can't cast to T.

Is there a smarter and more type-safe approach?

P.S. this question is inspired by Unity.

CodePudding user response:

You can use (T)Convert.ChangeType(this.fooV1, typeof(T)). Check complete code below.

public class A {
private readonly float fooV1;
private readonly double fooV2;

public A(float foo) { this.fooV1 = foo; }
public A(double foo) { this.fooV2 = foo; }

public T GetFoo<T>() {
    if (typeof(T) == typeof(float)) { return (T)Convert.ChangeType(this.fooV1, typeof(T)); }
    if (typeof(T) == typeof(double)) { return (T)Convert.ChangeType(this.fooV2, typeof(T)); }
    throw new ArgumentException();
}

CodePudding user response:

You can hoodwink the compiler to say you know better by just casting it to object I guess (T)(object),

public T GetFoo<T>() {
    if (typeof(T) == typeof(float)) { return (T)(object)this.fooV1; }
    if (typeof(T) == typeof(double)) { return (T)(object)this.fooV2; }
    throw new ArgumentException();
}

You could get creative with the use of an operators, which will save the type being boxed or the use of a dynamic

public static implicit operator float(A a) => a.fooV1;
public static implicit operator double(A a) => a.fooV2;

Note : you could also do this the other way as well..

However, what you are doing is not really a good look, nothing will ever be compile time type safe and will always have the potential to produce runtime error or hard to understand problems, you should likely rethink your problem unfortunately

CodePudding user response:

I haven't tried it, but this could work

public dynamic GetFoo<T>()
{
  if (typeof(T) == typeof(float)) { return fooV1; }
  if (typeof(T) == typeof(double)) { return fooV2; }
  return new {};
}
float f = GetFoo<float>();
  •  Tags:  
  • c#
  • Related