Skip to content

Commit 8543e44

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

File tree

5 files changed

+156
-19
lines changed

5 files changed

+156
-19
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.sln.DotSettings

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -410,4 +410,5 @@
410410
<s:String x:Key="/Default/PatternsAndTemplates/StructuralSearch/Pattern/=EDE6DA5BB1FD144F81E051772A257749/ReplaceComment/@EntryValue">Update to fluent syntax.</s:String>
411411
<s:String x:Key="/Default/PatternsAndTemplates/StructuralSearch/Pattern/=EDE6DA5BB1FD144F81E051772A257749/ReplacePattern/@EntryValue">Assert.That($greater$, Is.GreaterThanOrEqualTo($lesser$));</s:String>
412412
<s:String x:Key="/Default/PatternsAndTemplates/StructuralSearch/Pattern/=EDE6DA5BB1FD144F81E051772A257749/SearchPattern/@EntryValue">Assert.GreaterOrEqual($greater$, $lesser$);</s:String>
413-
<s:String x:Key="/Default/PatternsAndTemplates/StructuralSearch/Pattern/=EDE6DA5BB1FD144F81E051772A257749/Severity/@EntryValue">HINT</s:String></wpf:ResourceDictionary>
413+
<s:String x:Key="/Default/PatternsAndTemplates/StructuralSearch/Pattern/=EDE6DA5BB1FD144F81E051772A257749/Severity/@EntryValue">HINT</s:String>
414+
<s:Boolean x:Key="/Default/UserDictionary/Words/=skipcq/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

src/NHibernate/Type/BooleanType.cs

Lines changed: 15 additions & 11 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; // skipcq: CS-P1003
18+
internal static readonly object FalseObject = false; // skipcq: CS-P1003
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
@@ -59,15 +63,9 @@ public override void Set(DbCommand cmd, object value, int index, ISessionImpleme
5963
cmd.Parameters[index].Value = (bool) value;
6064
}
6165

62-
public override string Name
63-
{
64-
get { return "Boolean"; }
65-
}
66+
public override string Name => "Boolean";
6667

67-
public override object DefaultValue
68-
{
69-
get { return false; }
70-
}
68+
public override object DefaultValue => FalseObject;
7169

7270
public override string ObjectToSQLString(object value, Dialect.Dialect dialect)
7371
{
@@ -89,7 +87,13 @@ public virtual object StringToObject(string xml)
8987
[Obsolete("This method has no more usages and will be removed in a future version.")]
9088
public override object FromStringValue(string xml)
9189
{
92-
return bool.Parse(xml);
90+
return GetBooleanAsObject(bool.Parse(xml));
91+
}
92+
93+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
94+
internal static object GetBooleanAsObject(bool value)
95+
{
96+
return value ? TrueObject : FalseObject;
9397
}
9498
}
9599
}

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)