Skip to content

Commit f560f7d

Browse files
authored
Cache boxed boolean values in BooleanType (#3230)
1 parent b7caea0 commit f560f7d

File tree

5 files changed

+162
-36
lines changed

5 files changed

+162
-36
lines changed

src/NHibernate.Test/Async/TypesTest/BooleanTypeFixture.cs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88
//------------------------------------------------------------------------------
99

1010

11-
using System;
11+
using System.Data.Common;
12+
using NHibernate.Engine;
1213
using NHibernate.Type;
14+
using NSubstitute;
1315
using NUnit.Framework;
1416

1517
namespace NHibernate.Test.TypesTest
@@ -21,10 +23,7 @@ namespace NHibernate.Test.TypesTest
2123
[TestFixture]
2224
public class BooleanTypeFixtureAsync : TypeFixtureBase
2325
{
24-
protected override string TypeName
25-
{
26-
get { return "Boolean"; }
27-
}
26+
protected override string TypeName => "Boolean";
2827

2928
[Test]
3029
public async Task ReadWriteAsync()
@@ -48,4 +47,4 @@ public async Task ReadWriteAsync()
4847
s.Close();
4948
}
5049
}
51-
}
50+
}

src/NHibernate.Test/TypesTest/BooleanTypeFixture.cs

Lines changed: 66 additions & 7 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
@@ -10,10 +12,7 @@ namespace NHibernate.Test.TypesTest
1012
[TestFixture]
1113
public class BooleanTypeFixture : TypeFixtureBase
1214
{
13-
protected override string TypeName
14-
{
15-
get { return "Boolean"; }
16-
}
15+
protected override string TypeName => "Boolean";
1716

1817
/// <summary>
1918
/// Verify Equals will correctly determine when the property
@@ -22,7 +21,7 @@ protected override string TypeName
2221
[Test]
2322
public void Equals()
2423
{
25-
BooleanType type = (BooleanType) NHibernateUtil.Boolean;
24+
BooleanType type = NHibernateUtil.Boolean;
2625

2726
Assert.IsTrue(type.IsEqual(true, true));
2827
Assert.IsTrue(type.IsEqual(false, false));
@@ -50,5 +49,65 @@ public void ReadWrite()
5049
s.Flush();
5150
s.Close();
5251
}
52+
53+
[Theory]
54+
public void GetByIndex(bool expected)
55+
{
56+
const int index0 = 0;
57+
const int index1 = 1;
58+
BooleanType type = NHibernateUtil.Boolean;
59+
var session = Substitute.For<ISessionImplementor>();
60+
var reader = Substitute.For<DbDataReader>();
61+
reader[index0].Returns(expected);
62+
reader[index1].Returns(expected);
63+
64+
var result0 = type.Get(reader, index0, session);
65+
var result1 = type.Get(reader, index1, session);
66+
67+
Assert.AreEqual(expected, (bool) result0);
68+
Assert.AreSame(result0, result1);
69+
}
70+
71+
[Theory]
72+
public void GetByName(bool expected)
73+
{
74+
const string name0 = "name0";
75+
const string name1 = "name1";
76+
BooleanType type = NHibernateUtil.Boolean;
77+
var session = Substitute.For<ISessionImplementor>();
78+
var reader = Substitute.For<DbDataReader>();
79+
reader[name0].Returns(expected);
80+
reader[name1].Returns(expected);
81+
82+
var result0 = type.Get(reader, name0, session);
83+
var result1 = type.Get(reader, name1, session);
84+
85+
Assert.AreEqual(expected, (bool) result0);
86+
Assert.AreSame(result0, result1);
87+
}
88+
89+
[Test]
90+
public void DefaultValue()
91+
{
92+
BooleanType type = NHibernateUtil.Boolean;
93+
94+
var result0 = type.DefaultValue;
95+
var result1 = type.DefaultValue;
96+
97+
Assert.IsFalse((bool) result0);
98+
Assert.AreSame(result0, result1);
99+
}
100+
101+
[Theory]
102+
public void StringToObject(bool expected)
103+
{
104+
BooleanType type = NHibernateUtil.Boolean;
105+
106+
var result0 = type.StringToObject(expected.ToString());
107+
var result1 = type.StringToObject(expected.ToString());
108+
109+
Assert.AreEqual(expected, result0);
110+
Assert.AreSame(result0, result1);
111+
}
53112
}
54-
}
113+
}
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: 17 additions & 19 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+
protected static readonly object TrueObject = true;
18+
protected static readonly object FalseObject = false;
19+
1620
/// <summary>
1721
/// Initialize a new instance of the BooleanType
1822
/// </summary>
@@ -36,38 +40,26 @@ 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

47-
public override System.Type PrimitiveClass
48-
{
49-
get { return typeof(bool); }
50-
}
51+
public override System.Type PrimitiveClass => typeof(bool);
5152

52-
public override System.Type ReturnedClass
53-
{
54-
get { return typeof(bool); }
55-
}
53+
public override System.Type ReturnedClass => typeof(bool);
5654

5755
public override void Set(DbCommand cmd, object value, int index, ISessionImplementor session)
5856
{
5957
cmd.Parameters[index].Value = (bool) value;
6058
}
6159

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

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

7264
public override string ObjectToSQLString(object value, Dialect.Dialect dialect)
7365
{
@@ -89,7 +81,13 @@ public virtual object StringToObject(string xml)
8981
[Obsolete("This method has no more usages and will be removed in a future version.")]
9082
public override object FromStringValue(string xml)
9183
{
92-
return bool.Parse(xml);
84+
return GetBooleanAsObject(bool.Parse(xml));
85+
}
86+
87+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
88+
internal static object GetBooleanAsObject(bool value)
89+
{
90+
return value ? TrueObject : FalseObject;
9391
}
9492
}
9593
}

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)