Skip to content

Commit a4b00bc

Browse files
committed
added cached boxed boolean values to BooleanType
it is faster and avoids memory allocations
1 parent ab5eb9d commit a4b00bc

File tree

4 files changed

+153
-11
lines changed

4 files changed

+153
-11
lines changed

src/NHibernate.Test/TypesTest/BooleanTypeFixture.cs

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
using System;
1+
using System.Data.Common;
2+
using NHibernate.Engine;
23
using NHibernate.Type;
4+
using NSubstitute;
35
using NUnit.Framework;
46

57
namespace NHibernate.Test.TypesTest
@@ -22,7 +24,7 @@ protected override string TypeName
2224
[Test]
2325
public void Equals()
2426
{
25-
BooleanType type = (BooleanType) NHibernateUtil.Boolean;
27+
BooleanType type = NHibernateUtil.Boolean;
2628

2729
Assert.IsTrue(type.IsEqual(true, true));
2830
Assert.IsTrue(type.IsEqual(false, false));
@@ -50,5 +52,65 @@ public void ReadWrite()
5052
s.Flush();
5153
s.Close();
5254
}
55+
56+
[Theory]
57+
public void GetByIndex(bool expected)
58+
{
59+
const int index0 = 0;
60+
const int index1 = 1;
61+
BooleanType type = NHibernateUtil.Boolean;
62+
var session = Substitute.For<ISessionImplementor>();
63+
var reader = Substitute.For<DbDataReader>();
64+
reader[index0].Returns(expected);
65+
reader[index1].Returns(expected);
66+
67+
var result0 = type.Get(reader, index0, session);
68+
var result1 = type.Get(reader, index1, session);
69+
70+
Assert.AreEqual(expected, (bool) result0);
71+
Assert.AreSame(result0, result1);
72+
}
73+
74+
[Theory]
75+
public void GetByName(bool expected)
76+
{
77+
const string name0 = "name0";
78+
const string name1 = "name1";
79+
BooleanType type = NHibernateUtil.Boolean;
80+
var session = Substitute.For<ISessionImplementor>();
81+
var reader = Substitute.For<DbDataReader>();
82+
reader[name0].Returns(expected);
83+
reader[name1].Returns(expected);
84+
85+
var result0 = type.Get(reader, name0, session);
86+
var result1 = type.Get(reader, name1, session);
87+
88+
Assert.AreEqual(expected, (bool) result0);
89+
Assert.AreSame(result0, result1);
90+
}
91+
92+
[Test]
93+
public void DefaultValue()
94+
{
95+
BooleanType type = NHibernateUtil.Boolean;
96+
97+
var result0 = type.DefaultValue;
98+
var result1 = type.DefaultValue;
99+
100+
Assert.IsFalse((bool) result0);
101+
Assert.AreSame(result0, result1);
102+
}
103+
104+
[Theory]
105+
public void StringToObject(bool expected)
106+
{
107+
BooleanType type = NHibernateUtil.Boolean;
108+
109+
var result0 = type.StringToObject(expected.ToString());
110+
var result1 = type.StringToObject(expected.ToString());
111+
112+
Assert.AreEqual(expected, result0);
113+
Assert.AreSame(result0, result1);
114+
}
53115
}
54-
}
116+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
using System.Data.Common;
2+
using NHibernate.Engine;
3+
using NHibernate.SqlTypes;
4+
using NHibernate.Type;
5+
using NSubstitute;
6+
using NUnit.Framework;
7+
8+
namespace NHibernate.Test.TypesTest
9+
{
10+
[TestFixture]
11+
public sealed class CharBooleanTypeFixture
12+
{
13+
[Theory]
14+
public void GetByIndex(bool expected)
15+
{
16+
const int index0 = 0;
17+
const int index1 = 1;
18+
CharBooleanType type =new CharBooleanTypeStub();
19+
var session = Substitute.For<ISessionImplementor>();
20+
var reader = Substitute.For<DbDataReader>();
21+
reader[index0].Returns(expected.ToString());
22+
reader[index1].Returns(expected.ToString());
23+
24+
var result0 = type.Get(reader, index0, session);
25+
var result1 = type.Get(reader, index1, session);
26+
27+
Assert.AreEqual(expected, (bool) result0);
28+
Assert.AreSame(result0, result1);
29+
}
30+
31+
[Theory]
32+
public void GetByName(bool value)
33+
{
34+
const string name = "0";
35+
const int index = 0;
36+
object expected = value;
37+
CharBooleanType type = Substitute.ForPartsOf<CharBooleanTypeStub>();
38+
var session = Substitute.For<ISessionImplementor>();
39+
var reader = Substitute.For<DbDataReader>();
40+
reader.GetOrdinal(name).Returns(index);
41+
type.Get(reader, index, Arg.Any<ISessionImplementor>()).Returns(expected);
42+
43+
var result = type.Get(reader, name, session);
44+
45+
Assert.AreSame(expected, result);
46+
}
47+
48+
[Theory]
49+
public void StringToObject(bool expected)
50+
{
51+
CharBooleanType type = new CharBooleanTypeStub();
52+
53+
var result0 = type.StringToObject(expected.ToString());
54+
var result1 = type.StringToObject(expected.ToString());
55+
56+
Assert.AreEqual(expected, result0);
57+
Assert.AreSame(result0, result1);
58+
}
59+
60+
public class CharBooleanTypeStub : CharBooleanType
61+
{
62+
public CharBooleanTypeStub() : base(new AnsiStringFixedLengthSqlType())
63+
{
64+
}
65+
66+
protected override string TrueString => true.ToString();
67+
68+
protected override string FalseString => false.ToString();
69+
}
70+
}
71+
}

src/NHibernate/Type/BooleanType.cs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Data;
33
using System.Data.Common;
4+
using System.Runtime.CompilerServices;
45
using NHibernate.Engine;
56
using NHibernate.SqlTypes;
67

@@ -13,6 +14,9 @@ namespace NHibernate.Type
1314
[Serializable]
1415
public class BooleanType : PrimitiveType, IDiscriminatorType
1516
{
17+
internal static readonly object TrueObject = true;
18+
internal static readonly object FalseObject = false;
19+
1620
/// <summary>
1721
/// Initialize a new instance of the BooleanType
1822
/// </summary>
@@ -36,12 +40,12 @@ public BooleanType(AnsiStringFixedLengthSqlType sqlType) : base(sqlType)
3640

3741
public override object Get(DbDataReader rs, int index, ISessionImplementor session)
3842
{
39-
return Convert.ToBoolean(rs[index]);
43+
return GetBooleanAsObject(Convert.ToBoolean(rs[index]));
4044
}
4145

4246
public override object Get(DbDataReader rs, string name, ISessionImplementor session)
4347
{
44-
return Convert.ToBoolean(rs[name]);
48+
return GetBooleanAsObject(Convert.ToBoolean(rs[name]));
4549
}
4650

4751
public override System.Type PrimitiveClass
@@ -66,7 +70,7 @@ public override string Name
6670

6771
public override object DefaultValue
6872
{
69-
get { return false; }
73+
get { return FalseObject; }
7074
}
7175

7276
public override string ObjectToSQLString(object value, Dialect.Dialect dialect)
@@ -89,7 +93,13 @@ public virtual object StringToObject(string xml)
8993
[Obsolete("This method has no more usages and will be removed in a future version.")]
9094
public override object FromStringValue(string xml)
9195
{
92-
return bool.Parse(xml);
96+
return GetBooleanAsObject(bool.Parse(xml));
97+
}
98+
99+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
100+
internal object GetBooleanAsObject(bool value)
101+
{
102+
return value ? TrueObject : FalseObject;
93103
}
94104
}
95105
}

src/NHibernate/Type/CharBooleanType.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
using System.Data.Common;
44
using NHibernate.Engine;
55
using NHibernate.SqlTypes;
6-
using NHibernate.Util;
76

87
namespace NHibernate.Type
98
{
@@ -37,7 +36,7 @@ public override object Get(DbDataReader rs, int index, ISessionImplementor sessi
3736
}
3837
else
3938
{
40-
return code.Equals(TrueString, StringComparison.InvariantCultureIgnoreCase);
39+
return GetBooleanAsObject(code.Equals(TrueString, StringComparison.InvariantCultureIgnoreCase));
4140
}
4241
}
4342

@@ -68,11 +67,11 @@ public override object StringToObject(String xml)
6867
{
6968
if (string.Equals(TrueString, xml, StringComparison.InvariantCultureIgnoreCase))
7069
{
71-
return true;
70+
return TrueObject;
7271
}
7372
else if (string.Equals(FalseString, xml, StringComparison.InvariantCultureIgnoreCase))
7473
{
75-
return false;
74+
return FalseObject;
7675
}
7776
else
7877
{

0 commit comments

Comments
 (0)