1
public class ImgBuffer<T>
{
    public T[] buf;
    public int width;
    public int height;
    public ImgBuffer () {}
    public ImgBuffer (int w, int h)
    {
        buf = new T[w*h];
        width = w;
        height = h;
    }

    public void Mirror()
    {
        ImageTools.Mirror (ref buf, width, height);
    }
}

And the ImageTools class has Mirror defined for byte[], short[], and Color32[] on the fist argument. In particular:

public void Mirror(ref Color32[] buf, int width, int height) { ....

But I get this error:

error CS1502: The best overloaded method match for `ImageTools.Mirror(ref Color32[], int, int)' has some invalid arguments

What am I doing wrong?

4
  • Does ImageTools have a Mirror overload on string[]? Because I totally want to make a ImgBuffer<string>. I'll follow that up with an ImgBuffer<DateTime>. Commented Jan 17, 2012 at 4:06
  • Then how will the compiler know that a call to Mirror with a string array is legal? Commented Jan 17, 2012 at 4:09
  • Is this a joke? Am I using a string array? Color32 is a 4-byte structure (red, green, blue, alpha). I need various image (pixel) formats, with similar functionality. Commented Jan 17, 2012 at 4:11
  • 2
    No, it was actually not a joke. The compiler doesn't know that T will only by byte, short, or Color32. As far as the compiler is concerned, T could be string, DateTime. Those calls are not legal, and therefore you get your error message. Commented Jan 17, 2012 at 4:15

2 Answers 2

4

It looks like you expect C# generics to be something like a template. That's not the case. From your description, it appears there is an ImageTools class that looks something like this

public class ImageTools
{
    public static void Mirror(ref byte[] buf, int width, int height) { }
    public static void Mirror(ref Color32[] buf, int width, int height) { }
    public static void Mirror(ref short[] buf, int width, int height) { }
}

And you have an ImgBuffer class that looks like this (abbreviated)

public class ImgBuffer<T>
{
    public T[] buf;
    public int width;
    public int height;

    public void Mirror()
    {
        ImageTools.Mirror(ref buf, width, height);
    }
}

The compiler cannot verify in ImgBuffer.Mirror that the call to ImageTools.Mirror is legal. All the compiler knows about ref buf is that it is of type T[]. The T could be anything. It could be string, int, DateTime, Foo, etc. The compiler is unable to verify that the arguments are correct, and therefore your code is illegal.

This would be legal, but I have a feeling that you have specific implementations for your Mirror methods for your 3 desired types, so it's probably not workable.

public class ImageTools<T>
{
    public static void Mirror(ref T[] buf, int width, int height) { }
}
Sign up to request clarification or add additional context in comments.

5 Comments

I see. Yes this is my first foray into C# generics, I was a C++ template guy before. Thank you. So is there a way to fix this without defining a Mirror for every conceivable data type? Casting or constraints?
Constraints will not work for you here. Constraints can be applied to limit T to a struct or a class, to an interface or given base class, to items with parameterless constructors. You cannot limit them to say "I want T to be byte, short, or Color32."
Right. I could rework the ImageTools class to be generic, but it needs to perform well (each of these operations is currently optimized for its particular data type. For example, mirroring a short just swaps shorts, but mirroring a Color32 needs to move (in essence) a 4-byte long) Can I detect which type is 'coming in' and switch algorithms?
I would probably go for some regular, old-fashioned polymorphism and just have a ByteImageBuffer, ShortImageBuffer, Color32ImageBuffer, but I don't know enough about your problem. Generics do not appear to be the right answer. Even if you went with generic ImageTools class, you could try to use it with any given T, which doesn't seem to fit your design. You could do (if typeof(T) == typeof(byte)) to switch algorithms, but that is also messy.
Forever will it dominate your destiny.
0

You need to scope your generic type argument. For example:

public class ImgBuffer<T> where T : Color32
{
    public T[] buf;
    public int width;
    public int height;
    public ImgBuffer () {}
    public ImgBuffer (int w, int h)
    {
        buf = new T[w*h];
        width = w;
        height = h;
    }

    public void Mirror()
    {
        ImageTools.Mirror (ref buf, width, height);
    }
}

1 Comment

As Anthony Pegram has correctly inferred, I need this to work for several classes, and listing Color32, short, byte etc. does not work (compiler always says the last class in the list must come first)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.