Question

I have a utility class called ImageProperty which is used to store the type and value of a specific image property.

The type can only be one of the following enum values:

public enum ImagePropertyType { SIZE, H_RES, V_RES, BIT_COUNT, IS_ALPHA }

The values are all of different types (Size, float, float, int, bool).

A simplified form of my ImageProperty class is as follows:

public class ImageProperty
{
    private ImagePropertyType type;
    private object value;

    public ImageProperty(ImagePropertyType type, object value)
    {
        this.type = type;
        this.value = value;
    }

    public ImagePropertyType getType()
    {
        return this.type;
    }

    public void setType(ImagePropertyType type)
    {
        this.type = type
    }

    public object getValue()
    {
        return this.value;
    }        

    public void setValue(object value)
    {
        this.value = value;
    }
}

Note the use of object for getting/setting the value (since the types vary).

I want to make my class generic since I do not like using object so I make a few changes to the class and methods:

public class ImageProperty<T>
{
    ...
    private T value;
    ...
    public ImageProperty(ImagePropertyType type, T value)
    ...
    public T getValue()
    ...
    public void setValue(T value)
    ...
}    

I have a function in another class that needs to return an instance of ImageProperty based on the type given.

public ???? getImageProperty(ImagePropertyType type, Bitmap bitMap)
{
    switch(type)
    {     
        case SIZE:
            return new ImageProperty<Size>(type, bitMap.Size);
        case H_RES:
            return new ImageProperty<float>(type, bitMap.HorizontalResolution);
        case V_RES:                            
            return new ImageProperty<float>(type, bitMap.VerticalResolution);
        ...
        ...
    }
}

I am not sure of what return type to put for this method (hence the ????).

I can't just put:

public ImageProperty getImageProperty(ImagePropertyType type, Bitmap bitMap)

because the ImageProperty class needs to be parameterized.

Obviously, if the value type were always, lets say, int I would set the return type to:

public ImageProperty<int> getImageProperty(ImagePropertyType type, Bitmap bitMap)

Is there a way to define the return type of getImageProperty to "any or unknown parameterized value"?

Something like:

public ImageProperty<?> getImageProperty(ImagePropertyType type, Bitmap bitMap)

Is parameterizing the class is not a good idea since I don't know about the type of value that is going to be returned?

Should I just make the ImageProperty class non-generic (like the first class in my post) and go back to using object for the return type and if I need to know the value type I can just get it using typeof?

object value = getImageProperty(ImagePropertyType.SIZE, Bitmap bitMap).getValue();
Type t = typeof(value);

Thank you.

----UPDATE---------------------------------

Based on Knaģis' suggestion and further reading I decided to keep the original class then make a generic class that extends ImageProperty:

public class ImageProperty<T> : ImageProperty
{
    private T propertyValue;

    public ImageProperty()
        : base()
    {
    }

    public ImageProperty(ImagePropertyType propertyType, T propertyValue)
        : base(propertyType, propertyValue)
    {
        this.propertyValue = propertyValue;
    }

    public T getPropertyValue()
    {
        return propertyValue;
    }

    public void setPropertyValue(T propertyValue)
    {
        this.propertyValue = propertyValue;
    }
}    

One thing, however. I am getting a compiler warning that says:

ImageProperty<T>.getPropertyValue() hides inherited member ImageProperty.getPropertyValue(). Use the new keyword if hiding was intended.

I added the new keyword:

public new T getPropertyValue()

Strange, I never knew about the new keyword being used in a method declaration and how it's used. Anyone care to explain?


Was it helpful?

Solution

In your case the only thing you can do is to ask for the method to return a certain type:

public ImageProperty<T> getImageProperty<T>(ImagePropertyType type, Bitmap bitMap)

// call the method
ImageProperty<int> result = obj.getImageProperty<int>(ImagePropertyType.SIZE, bitmap).

That type T must be known by the caller, otherwise the compiler won't be able to make sense of your code. If you don't know it always then your generic class must inherit from a non-generic base class and the method will then return the non-generic type that can be later cast to the specific generic implementation.

// class
public class ImageProperty<T> : ImageProperty {}

// and methods that can be used (you can only use one of these unless you rename one)
public ImageProperty<T> getImageProperty<T>(ImagePropertyType type, Bitmap bitMap)
public ImageProperty getImageProperty(ImagePropertyType type, Bitmap bitMap)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top