如何使用具有整数溢出(字节)的属性?
How to use properties with an integral overflow (byte)?
我对编程和 C# 还很陌生,我正在使用 C# 9.0 创建一个游戏,其中 Entity
的所有实例都有特定的统计数据。我希望能够使用属性更改他们的私有数据字段,尽管我不完全确定属性是如何工作的。我知道它们在作为 getter 和 setter 封装时很有用。
上下文:
- 我正在尝试优化代码并尽可能减少内存使用
- 字节字段
str
应该是可变的(通过事件、训练等),但有“上限”和“下限”
- 如果
dog.str
= 253,那么 dog.Str += 5;
应该导致 dog.str
为 255
- 如果
dog.str
= 2,那么 dog.Str -= 5;
应该导致 dog.str
为 0
private byte str;
public short Str
{
get => str;
set
{
if (value > byte.MaxValue) str = byte.MaxValue; //Pos Overflow
else if (value < byte.MinValue) str = byte.MinValue; //Neg Overflow
else str = (byte)value;
}
}
问题:
由于属性的数据类型是Short,它是否创建了一个消耗内存的新私有支持字段?或者 value
/Str{set;}
只是一个稍后消失的局部变量?
- 属性
public float StrMod {get => (float)(str*Effects.Power);}
是否创建了支持字段?只创建一个像 public float getStrMod()
这样的方法会更好吗?
此代码是否最适合我要实现的目标?考虑到以下情况,是否有更好的方法来做到这一点?
- 如果由于某种原因 Short 溢出(在这种情况下不太可能,但可能会出现类似情况),那么我最终会遇到同样的问题。但是,如果额外的内存分配不是问题,那么我可以使用 int。
{get;}
将 return 短片,这可能是也可能不是问题。
问题一:
不,它不是,它的支持字段是 str
。
问题二:
首先分析您的代码,而不是进行随机更改以减少内存使用。
“过早的优化是万恶之源”,你现在真的有这样的问题吗?
我个人会使用 int
并为 属性 使用相同的类型,为了简单起见,支持字段。
这将避免诸如分配 32768
之类的换行,这将导致 short
的 -32768
。
旁注,不要认为使用 byte
一定会产生 1 个字节,如果您有严格的打包要求,那么您需要查看 StructLayoutAttribute.Pack
。
除此之外,我看不出您的代码有什么问题,只需让它运行先然后优化它!
下面是我编写代码的方式,也许您会从中得到一些想法:
class Testing
{
private int _value;
public int Value
{
get => _value;
set => _value = Clamp(value, byte.MinValue, byte.MaxValue);
}
private static int Clamp(int value, int min, int max)
{
return Math.Max(min, Math.Min(max, value));
}
}
编辑:
不同场景:
class Testing
{
private int _value1;
public int Value1 // backing field is _value1
{
get => _value1;
set => _value1 = value;
}
public int Value2 { get; set; } // adds a backing field
public int Value3 { get; } // adds a backing field
public int Value4 => 42; // no backing field
}
正如您可能已经猜到的那样,属性是 syntactic sugar 方法,与只能为其赋值的字段相比,它们可以在后台执行 'whatever'。
此外,与方法的一个区别是您可以在调试器中浏览它的值,这很方便。
推荐阅读:
https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/properties
最后,属性预计 return 很快,否则写一个方法,如果需要一段时间,可能 async
(在这种情况下方法的优点是属性不能async
).
@aybe 回答涵盖了关于你问题的主要内容。我想为您的第二个问题添加更多信息。您应该考虑在哪个平台上编写应用程序。有一个word term:
In computing, a word is the natural unit of data used by a particular
processor design. A word is a fixed-sized piece of data handled as a
unit by the instruction set or the hardware of the processor. The
number of bits in a word (the word size, word width, or word length)
is an important characteristic of any specific processor design or
computer architecture.
如果处理器有64位字,那么每个类型小于64位的变量在内存中仍然占用64位。请记住,给定类型的变量将按给定类型处理,内存中的大小不会影响范围、上溢或下溢 - 将为给定类型处理算术。
简而言之 - 如果您有 64 位台式机处理器并且您将仅使用 short
个变量,那么与声明 int
个变量相比,您不会观察到任何内存节省。
我对编程和 C# 还很陌生,我正在使用 C# 9.0 创建一个游戏,其中 Entity
的所有实例都有特定的统计数据。我希望能够使用属性更改他们的私有数据字段,尽管我不完全确定属性是如何工作的。我知道它们在作为 getter 和 setter 封装时很有用。
上下文:
- 我正在尝试优化代码并尽可能减少内存使用
- 字节字段
str
应该是可变的(通过事件、训练等),但有“上限”和“下限”- 如果
dog.str
= 253,那么dog.Str += 5;
应该导致dog.str
为 255 - 如果
dog.str
= 2,那么dog.Str -= 5;
应该导致dog.str
为 0
- 如果
private byte str;
public short Str
{
get => str;
set
{
if (value > byte.MaxValue) str = byte.MaxValue; //Pos Overflow
else if (value < byte.MinValue) str = byte.MinValue; //Neg Overflow
else str = (byte)value;
}
}
问题:
由于属性的数据类型是Short,它是否创建了一个消耗内存的新私有支持字段?或者
value
/Str{set;}
只是一个稍后消失的局部变量?- 属性
public float StrMod {get => (float)(str*Effects.Power);}
是否创建了支持字段?只创建一个像public float getStrMod()
这样的方法会更好吗?
- 属性
此代码是否最适合我要实现的目标?考虑到以下情况,是否有更好的方法来做到这一点?
- 如果由于某种原因 Short 溢出(在这种情况下不太可能,但可能会出现类似情况),那么我最终会遇到同样的问题。但是,如果额外的内存分配不是问题,那么我可以使用 int。
{get;}
将 return 短片,这可能是也可能不是问题。
问题一:
不,它不是,它的支持字段是 str
。
问题二:
首先分析您的代码,而不是进行随机更改以减少内存使用。
“过早的优化是万恶之源”,你现在真的有这样的问题吗?
我个人会使用 int
并为 属性 使用相同的类型,为了简单起见,支持字段。
这将避免诸如分配 32768
之类的换行,这将导致 short
的 -32768
。
旁注,不要认为使用 byte
一定会产生 1 个字节,如果您有严格的打包要求,那么您需要查看 StructLayoutAttribute.Pack
。
除此之外,我看不出您的代码有什么问题,只需让它运行先然后优化它!
下面是我编写代码的方式,也许您会从中得到一些想法:
class Testing
{
private int _value;
public int Value
{
get => _value;
set => _value = Clamp(value, byte.MinValue, byte.MaxValue);
}
private static int Clamp(int value, int min, int max)
{
return Math.Max(min, Math.Min(max, value));
}
}
编辑:
不同场景:
class Testing
{
private int _value1;
public int Value1 // backing field is _value1
{
get => _value1;
set => _value1 = value;
}
public int Value2 { get; set; } // adds a backing field
public int Value3 { get; } // adds a backing field
public int Value4 => 42; // no backing field
}
正如您可能已经猜到的那样,属性是 syntactic sugar 方法,与只能为其赋值的字段相比,它们可以在后台执行 'whatever'。
此外,与方法的一个区别是您可以在调试器中浏览它的值,这很方便。
推荐阅读:
https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/properties
最后,属性预计 return 很快,否则写一个方法,如果需要一段时间,可能 async
(在这种情况下方法的优点是属性不能async
).
@aybe 回答涵盖了关于你问题的主要内容。我想为您的第二个问题添加更多信息。您应该考虑在哪个平台上编写应用程序。有一个word term:
In computing, a word is the natural unit of data used by a particular processor design. A word is a fixed-sized piece of data handled as a unit by the instruction set or the hardware of the processor. The number of bits in a word (the word size, word width, or word length) is an important characteristic of any specific processor design or computer architecture.
如果处理器有64位字,那么每个类型小于64位的变量在内存中仍然占用64位。请记住,给定类型的变量将按给定类型处理,内存中的大小不会影响范围、上溢或下溢 - 将为给定类型处理算术。
简而言之 - 如果您有 64 位台式机处理器并且您将仅使用 short
个变量,那么与声明 int
个变量相比,您不会观察到任何内存节省。