C# 防止字节在递增超过255时返回0

C# 防止字节在递增超过255时返回0,c#,xna,C#,Xna,我正在为我正在学习的C#/XNA类编写一个XNA3.1应用程序。这是一个非常简单的介绍性任务,用户只需更改屏幕的颜色,按键盘上的R、G或B按钮选择颜色通道,然后按向上和向下箭头来增加或减少该通道的值 如果我在255之后增加一个字节,它会返回到0,反之亦然,进行递减,大概是因为C在对字节进行算术运算时,实际上会将字节转换为int。然而,我的教授特别要求,一旦通道达到其最大值或最小值,如果用户试图超出这些界限,它将保持在那里。我自己想出了一个办法来解决这个问题,但当我在这里或谷歌上搜索此类问题的解决

我正在为我正在学习的C#/XNA类编写一个XNA3.1应用程序。这是一个非常简单的介绍性任务,用户只需更改屏幕的颜色,按键盘上的R、G或B按钮选择颜色通道,然后按向上和向下箭头来增加或减少该通道的值

如果我在
255
之后增加一个字节,它会返回到
0
,反之亦然,进行递减,大概是因为C在对
字节进行算术运算时,实际上会将
字节
转换为
int
。然而,我的教授特别要求,一旦通道达到其最大值或最小值,如果用户试图超出这些界限,它将保持在那里。我自己想出了一个办法来解决这个问题,但当我在这里或谷歌上搜索此类问题的解决方案时,我什么也没找到。我就是这样解决这个问题的:

/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
    // ...

    Color color;

    private int Red
    {
        set { color.R = NoWrapIntToByte(value); }
        get { return (int)color.R; }
    }

    private int Green
    {
        set { color.G = NoWrapIntToByte(value); }
        get { return (int)color.G; }
    }

    private int Blue
    {
        set {color.B = NoWrapIntToByte(value); }
        get { return (int)color.B; }
    }

    /// <summary>
    /// Converts an integer to a byte but doesn't wrap.
    /// </summary>
    /// <param name="x"></param>
    /// <returns></returns>
    static byte NoWrapIntToByte(int x)
    {
        if (x < Byte.MinValue)
            return Byte.MinValue;
        else if (x > Byte.MaxValue)
            return Byte.MaxValue;
        else
            return (byte)x;
    }
}
编译器会抱怨的。但是,当用户按下向上或向下箭头时,该颜色通道将递增或递减,如果通道递减到0以下或递增到255以上,则该颜色通道将换行。我使用
int
作为通道属性的类型,因为如果我使用
Red-=1
Red+=1
之类的东西,如果我越界,会出现不同的期望。如果我加的话,我希望得到的值比原始值小,反之亦然,如果我减的话。我使用的是
int
,因为它允许我在属性中检测并相应地进行处理

我认为我的解决方案是可以的,但我很好奇我是否忽略了什么。我不是唯一一个试图解决这个问题的人,所以我很好奇解决这个问题的惯用或最佳实践方法是什么。我不是在问我的家庭作业问题的答案,因为我已经有了一个有效的解决方案。然而,我对C#不太了解,所以我很好奇是否有一种更简单的方法来做同样的事情,或者使用比我这里更少的代码。我知道我可以让C#抛出一个
溢出
异常,但这需要更改项目设置,而且它也没有告诉我具体是哪种类型


谢谢

我想我不可能阻止它包装。您应该使用int16或int32。但是,您可以使用if语句检查结果是否大于255,然后将其转换。

您的答案似乎应该满足您的要求,但要达到这一点需要编写大量代码。如果这是我要解决的问题,我可能会做类似的事情:

static byte NoWrapIntToByte(int x)
{
    int tmp;
    tmp = Math.Max(x, 0);
    tmp = Math.Min(255, tmp);
    return (byte)tmp;
}
private int Red
{
    get { return (int)color.R; }
    set { 
        if (value < 0 || value > 255) throw new ArgumentOutOfRangeException();
        color.R = (byte)value;
    }
}
感谢@Marlon提供的
Math.Max/Min
fix

感谢@Andrew Noyes的演员安排


希望这有帮助。:)

您的解决方案可行,但从根本上说是错误的方法。你应该这样写你的财产:

static byte NoWrapIntToByte(int x)
{
    int tmp;
    tmp = Math.Max(x, 0);
    tmp = Math.Min(255, tmp);
    return (byte)tmp;
}
private int Red
{
    get { return (int)color.R; }
    set { 
        if (value < 0 || value > 255) throw new ArgumentOutOfRangeException();
        color.R = (byte)value;
    }
}
private int Red
{
获取{return(int)color.R;}
集合{
如果(值<0 | |值>255)抛出新ArgumentOutOfRangeException();
color.R=(字节)值;
}
}
这让任何使用你的课程的人,包括你自己,都会陷入成功的深渊。之后,您将找到合适的解决方案,类似于以下内容:

private void IncrementRed_Click(object sender, EventArgs e) {
    if (this.Color.Red < 255) this.Color.Red += 1;
}
private void IncrementRed\u单击(对象发送方,事件参数e){
如果(this.Color.Red<255)this.Color.Red+=1;
}

然后,您可以通过让属性设置器引发PropertyChanged事件来进一步改进这一点。您可以在UI中订阅一个事件,将按钮的Enabled属性设置为false,以便用户立即清楚地看到,单击按钮不再有用。

可以定义一个新的结构,将一个字节包装在一组重载运算符和caster中,如下所示

struct NoWrapByte
{
    private byte _data;

    public NoWrapByte(byte data)
    {
        this._data = data;
    }

    public static NoWrapByte operator +(NoWrapByte a, NoWrapByte b)
    {
        if (a._data + b._data > 255)
            return new NoWrapByte((byte)255);
        else if (a._data + b._data < 0)
            return new NoWrapByte((byte)0);
        else
        return new NoWrapByte((byte)(a._data + b._data));
    }

    public static NoWrapByte operator -(NoWrapByte a, NoWrapByte b)
    {
        if (a._data - b._data > 255)
            return new NoWrapByte((byte)255);
        else if (a._data - b._data < 0)
            return new NoWrapByte((byte)0);
        else
            return new NoWrapByte((byte)(a._data - b._data));
    }

    public static implicit operator byte(NoWrapByte op)
    {
        return op._data;
    }
}
static byte NoWrapIntToByte(int x)
{
    return (byte)MathHelper.Clamp(x, 0, 255);
}
struct NoWrapByte
{
专用字节数据;
公共NoWrapByte(字节数据)
{
这个。_data=数据;
}
公共静态NoWrapByte运算符+(NoWrapByte a、NoWrapByte b)
{
如果(a._数据+b._数据>255)
返回新的NoWrapByte((字节)255);
否则如果(a._数据+b._数据<0)
返回新的NoWrapByte((字节)0);
其他的
返回新的NoWrapByte((字节)(a._数据+b._数据));
}
公共静态NoWrapByte运算符-(NoWrapByte a,NoWrapByte b)
{
如果(a._数据-b._数据>255)
返回新的NoWrapByte((字节)255);
否则如果(a._数据-b._数据<0)
返回新的NoWrapByte((字节)0);
其他的
返回新的NoWrapByte((byte)(a._数据-b._数据));
}
公共静态隐式运算符字节(NoWrapByte op)
{
返回操作单元数据;
}
}

我觉得您应该只使用XNA框架中内置的“钳制”方法

基本上,如果你想让一个值在0和255之间,那么你可以这样写

struct NoWrapByte
{
    private byte _data;

    public NoWrapByte(byte data)
    {
        this._data = data;
    }

    public static NoWrapByte operator +(NoWrapByte a, NoWrapByte b)
    {
        if (a._data + b._data > 255)
            return new NoWrapByte((byte)255);
        else if (a._data + b._data < 0)
            return new NoWrapByte((byte)0);
        else
        return new NoWrapByte((byte)(a._data + b._data));
    }

    public static NoWrapByte operator -(NoWrapByte a, NoWrapByte b)
    {
        if (a._data - b._data > 255)
            return new NoWrapByte((byte)255);
        else if (a._data - b._data < 0)
            return new NoWrapByte((byte)0);
        else
            return new NoWrapByte((byte)(a._data - b._data));
    }

    public static implicit operator byte(NoWrapByte op)
    {
        return op._data;
    }
}
static byte NoWrapIntToByte(int x)
{
    return (byte)MathHelper.Clamp(x, 0, 255);
}

这应该完全符合你的要求

字节x=256对于一个字节来说太大,255将是最大值,因此编译器是正确的。我认为你的解决办法很好。我会把它写成一个扩展,但那只是我自己。是的,我提到编译器会抱怨。也许我会添加一条注释以澄清问题……首先为什么要使用
int
?为什么不总是使用
字节
?这将避免大量的强制转换。因为我必须知道为什么字节会被包装。如果我超过255,一个整数将容纳256,。如果我小于0,整数将保持-1。一个字节就把信息扔掉了。@Andrew哦,好的。然后,如果我理解正确,一旦你得到了一个满意的解决方案,你会使用
byte
?或者还有其他一些约束要求使用
int
?你甚至不懂C,而且你是个专家!!:是的,你的函数比我的函数简单一点,但它们得到的结果是一样的。我想我真正的问题是这个函数