Strange Reflection problem - can't get it - c#

please help me understand what's going on in here and whether it should work like that ?
I have a generic list of objects from a CMS:
For example List<MyCMS.Articles.Article> myArticles = articles.All;
Later I output the contents of the list in a JSON format (for CMS UI - table list).
Now a single record would include:
article.Title
article.Alias
article.Guid
article.Description
+
article.SeoProperties.TitleOverride
article.SeoProperties.H1Tag
article.StateProperties.IsActive
article.StateProperties.Channels
etc...
as you can see an Article object has an additional class property - with common properties (used on other object types in the CMS)
I also use a filter class that does some filter operations with LINQ on the collection to return me only articles within a certain channel, for example...
So the problem is that when I serialize the collection as JSON - there are only a few "columns" that I really need to display in my table list, while I have no need in other fields - especially, possibly long fields such as "description" (lazy loaded from file system), etc... - I serialize with DataContractJsonSerializer...
I need a way to control what fields will be included in the JSON result... What I do is I use reflection to set property values to null if I don't need the property and
decorate class properties with [DataMember(IsRequired = false, EmitDefaultValue = false)] attributes... - it should work well - but - as soon as I go over (even cloned!!) collection of final objects to strip off the fields = set value to "null" - property value becomes null - application wide - in all collections of such objects... eh ?
Some demo code in here:
void Page_Load() {
MyCms.Content.Games games = new MyCms.Content.Games();
List<MyCms.Content.Games.Game> allGames = games.All;
MyCms.Content.Games games2 = new MyCms.Content.Games();
List<MyCms.Content.Games.Game> allGamesOther = games2.All;
Response.Write("Total games: " + allGames.Count + "<br />");
//This is our fields stripper - with result assigned to a new list
List<MyCms.Content.Games.Game> completelyUnrelatedOtherIsolated_but_notSureList = RemoveUnusedFields(allGamesOther);
List<MyCms.Content.Games.Game> gamesFiltered = allGames.Where(g=>g.GamingProperties.Software=="89070ef9-e115-4907-9996-6421e6013993").ToList();
Response.Write("Filtered games: " + gamesFiltered.Count + "<br /><br />");
}
private List<MyCms.Content.Games.Game> RemoveUnusedFields(List<MyCms.Content.Games.Game> games)
{
List<MyCms.Content.Games.Game> result = new List<MyCms.Content.Games.Game>();
if (games != null && games.Count > 0)
{
//Retrieve a list of current object properties
List<string> myContentProperties = MyCms.Utils.GetContentProperties(games[0]);
MyCms.PropertyReflector pF = new MyCms.PropertyReflector();
foreach (MyCms.Content.Games.Game contentItem in games)
{
MyCms.Content.Games.Game myNewGame = (MyCms.Content.Games.Game)contentItem.Clone();
myNewGame.Images = "wtf!"; //just to be sure we do set this stuff not only null
pF.SetValue(myNewGame, "GamingProperties.Software", ""); //set one property to null for testing
result.Add(myNewGame);
}
}
return result;
}
Objects are set to their "Default values" (basically, null, in most cases) with this:
private object GetDefaultValue(Type type)
{
if (type.IsValueType)
{
try
{
return Activator.CreateInstance(type);
}
catch {
return null;
}
}
return null;
}

Quite probably your having trouble with differentiating between a shallow copy and a deep copy.
If a field is a value type, a bit-by-bit copy of the field is performed. If a field is a reference type, the reference is copied but the referred object is not; therefore, the original object and its clone refer to the same object.
With a deep copy when you clone an object and that object has a field of reference type, a new clone of that object is created and assigned to the field (vs just referencing the first object). Thus you have to completely different objects that share nothing.
That means if you're using clone and some of the properties are in fact subproperties (that is, properties of an instance inside the original object) you're changing it application wide, because you're acting upon a reference, not a new instance of the subobject.
You have more information about it in
http://msdn.microsoft.com/en-us/library/system.object.memberwiseclone.aspx

You could create a kind of modelview classes with the necessary fields and use something like Automapper to fill them. By this way, you will have a nice code, easy to maintain and highly customizable.

Related

C# Confusion around List of object references seemingly not referring to the same object

I have a class which has some object fields and I then make a list out of those fields. But I'm confused about how many objects actually exist.
I think the List is a reference type so modifying an object from the list should also modify the field
But if I modify the List & set an item equal to a new object, it only changes the list, not the field
public class MyClass{
public string MyProperty { get; set; } = "Default value";
}
public class TestClass{
private MyClass objectField = new MyClass();
public void run(){
List<MyClass> listOfObjects = new List<MyClass> { objectField };
//Both objectField and listOfObjects[0] have the same value
listOfObjects[0].MyProperty = "Changed value 1st time";
//objectField is "Default value" and listOfObjects[0] is "Changed value 2nd time"
listOfObjects[0].MyProperty = new MyClass();
listOfObjects[0].MyProperty = "Changed value 2nd time";
}
public static void Main() {
TestClass tester = new TestClass();
tester.run();
}
}
Why are there now seemingly 2 objects now? Did the new destroy the reference to the field?
Is there a way to make the field still refer to the new object I create in the list?
This is a simply example, but I have a large list and don't want to have to go and manually update the fields to the values in the list
listOfObjects[0] = new MyClass();
listOfObjects[0].MyProperty = "Changed value 2nd time";
objectField=listOfObjects[0]; //I want to avoid this
Edit (Clarifications)
The real scenario has many object fields of the same base class
I wanted to do the same thing (change property values or instantiate new objects) to all my fields at once so I thought I could just put the fields in a List
I still wanted to be able to refer to the object via it's field name, not just the List index but it appears it can't be done
I'm going to go on a few assumptions here, as your code would not normally compile. Anyways, a generic List<> in C#, when the generic type is a class (reference) type, is a collection of references to those classes, but not a direct pointer to a local object that you put into it.
So basically you have a bunch of class objects hanging out in memory and the list just has references to them. As soon as you new up a new object and REPLACE at one of the indexes, you are replacing the reference to the object in the collection with the new object (not the object in memory itself). The local field still has the reference to the old object.
//E.G.
var objectField = new MyClass();
var listOfObjects = new List<MyClass>{ bjectField };
// Here you are modifying the property of the original object
listOfObjects[0].MyProperty = "1st change";
// Here you are replacing the reference to that object with
// with a reference to a new object, so the properties are totally fresh
// properties go with the old object, a new object has all new fields / properties
// and references
// also, this does not replace the reference to your local field / property
listOfObjects[0] = new MyClass();
// here you are modifying the property on the new object, not the original
listOfObjects[0].MyProperty = "2nd change";
The field, or property belongs to that object. A class in C# is not some structure that you can overlay with a new struct and assume that the fields / properties will just pick up the references to the old fields / properties.
Additionally, passing a local field into a collection does not mean you are giving it a pointer to that field, you are giving it a reference to that object. Even in C++, you would have to specify that you were passing in a pointer to that particular field / property. You cannot do "pointer magic" in C# like you can in C or C++ and change a pointer to a new object (well you can but then you have to do unsafe code, don't do it unless you are interacting with native code structures).
TL;DR; Passing a field into a collection does not mean you are passing a direct pointer to that field into the collection. Therefore, replacing it in the collection does not change your local field.

How to check whether model have some changes in C# MVC

I have appSourceInfoModel taken from Database, now i am passing ViewModel i.e. reviewerAppsBacklogViewModel and if reviewerAppsBacklogViewModel and appSourceInfoModel are same then do not update database if there are changes then Update. I am doing, first assigning to variable var DBappSourceInfoModel = appSourceInfoModel; then I assigning some values to appSourceInfoModel then comparing the initially saved model DBappSourceInfoModel and appSourceInfoModel. But, assigning some values to appSourceInfoModel also change values in the initially saved model DBappSourceInfoModel. All of the code can be found below.
AppSourceInfo appSourceInfoModel = _appSourceInfoRepository.Get(a => a.Review.ReviewId == reviewId);
var DBappSourceInfoModel = appSourceInfoModel; //Initially save Model in var
appSourceInfoModel.Cost = reviewerAppsBacklogViewModel.Cost;
appSourceInfoModel.InProgress = true;
appSourceInfoModel.PegiRating = reviewerAppsBacklogViewModel.PegiRating;
appSourceInfoModel.Rating = reviewerAppsBacklogViewModel.AverageUserReviewsRating;
appSourceInfoModel.DownloadCounter = reviewerAppsBacklogViewModel.NoofDownloadsFromSource;
appSourceInfoModel.ReviewCounter = reviewerAppsBacklogViewModel.NoofReviewOfSource;
appSourceInfoModel.StoreCategory = reviewerAppsBacklogViewModel.StoreCategory;
var IsAppSourceInfoModelChanged = !DBappSourceInfoModel.Equals(appSourceInfoModel);
if (IsAppSourceInfoModelChanged)
{
_appSourceInfoRepository.Update(appSourceInfoModel);
}
I have Solved it using this simple Code in My Model i.e. AppSourceInfo
public object Clone()
{
return this.MemberwiseClone();
}
and change the following code
var DBappSourceInfoModel = appSourceInfoModel; //Initially save Model in var
to
var DBappSourceInfoModel = (AppSourceInfo) appSourceInfoModel.Clone();
You need to perform a Copy (shallow probably sufficient)
var DBappSourceInfoModel = appSourceInfoModel;
Is simply creating a reference to the same object. Implement ICloneable on the DBappSourceInfoModel then use Clone method,
Your Clone method needs to copy all the info to the new Object, also performing Deep Copies on internal references if needed,
This will copy all the details to the other object and create two separate objects,
look here for reference:
https://msdn.microsoft.com/en-us/library/system.icloneable%28v=vs.110%29.aspx
EDIT
Just to be clear, you also need to use the IComparable interface to define how the objects are compared for equality,
https://msdn.microsoft.com/en-us/library/system.icomparable%28v=vs.110%29.aspx

Why are all the collections in my POCO are null when deserializing some valid json with the .NET Newtonsoft.Json component

Problem
When trying to deserialize some Json using Newtonsoft's Json.NET nuget library my collection-properties are null when I do NOT provide a JsonSerializerSettings - why?
Details
I have some valid json data and deserializing it into my custom class / POCO. Now, all the simple properties (like strings, int's, etc) all get set correctly. My simple child classes also get set properly (eg. a User property or a BuildingDetails property, etc).
All my collections are null, though. The setters are never called (I've put a break point in there and they don't get set, but the others do get called/set).
eg. property.
List<Media> Images { get { ... } set { ... } }
eg.
var foo = new Foo();
var json = JsonConvert.Serialize(foo);
var anotherFoo = JsonConvert.Deserialize<Foo>(json);
// the collection properties on anotherFoo are null
Now - this is the crazy thing: when I use a JsonSerializerSettings it now works:
// NOTE: ModifiedDataContractResolver <-- skips any property that is a type
/ ModifiedData (which is a simple custom class I have).
var settings = new JsonSerializerSettings
{
ContractResolver = new ModifiedDataContractResolver(),
ObjectCreationHandling = ObjectCreationHandling.Replace,
Formatting = Formatting.Indented
};
var foo = new Foo();
var json = JsonConvert.Serialize(foo, settings);
var anotherFoo = JsonConvert.Deserialize<Foo>(json, settings);
my collections are now set!
Take note of this: ObjectCreationHandling = ObjectCreationHandling.Replace. This is the magical setting that makes things work.
What is this doing and why does not having this setting mean my collections are not getting set/created/etc?
Another clue. If I do not have the setter, collection is null / not set. If I have the setter like this, it fails too:
public List<Media> Images
{
get { return new List<Media> { new Media{..}, new Media{..} }; }
set { AddImages(value); }
}
If I do NOT return the list, in the getter the collection is SET! IT WORKS!
private List<Media> _images;
public List<Media> Images
{
get { return _images; }
set { AddImages(value); }
}
Notice how it's now just using a baking field instead?
It's like there's some weird connection/correlation between the collection's GETTER property and result and how Json.net sets this data using the auto setting?
Your problem is that the property you are trying to deserialize gets and sets a proxy collection rather than a "real" collection in your object graph. Doing so falls afoul of an implementation decision about the algorithm Json.NET uses to construct and populate properties returning reference type objects, collections and dictionaries. That algorithm is:
It calls the getter in the parent class to get the current value of the property being deserialized.
If null, and unless a custom constructor is being used, it allocates an instance of the property's returned type (using the JsonContract.DefaultCreator method for the type).
It calls the setter in the parent to set the allocated instance back into the parent.
It proceeds to populate the instance of the type.
It does not set the instance back a second time, after it has been populated.
Calling the getter at the beginning makes it possible to populate an instance of a type (e.g. with JsonConvert.PopulateObject()), recursively populating any pre-allocated instances of other types to which the type refers. (That's the purpose of the existingValue parameter in JsonConverter.ReadJson().)
However, the ability to populate a pre-allocated object graph in this manner comes with a cost: each object encountered in the graph must be the real object and not some proxy object created for serialization purposes. If the object returned by the getter is just some proxy, the proxy will get populated, and not the "real" object - unless the proxy has some sort of mechanism to pass changes to its data back to its originator.
(While this decision may seem undesirable, it's not unusual; XmlSerializer works the same way. For a list of serializers that do this, see XML Deserialization of collection property with code defaults.)
ObjectCreationHandling = ObjectCreationHandling.Replace, as you have observed, changes this algorithm, so that collections are allocated, populated, and set back. That is one way to enable deserialization of proxy collections.
As another workaround, you could choose instead to serialize and deserialize a proxy array:
[JsonIgnore]
public List<Media> Images
{
get { return new List<Media> { new Media{..}, new Media{..} }; }
set { AddImages(value); }
}
[JsonProperty("Images")] // Could be private
Media [] ImagesArray
{
get { return Images.ToArray(); }
set { AddImages(value); }
}
For arrays, Json.NET (and XmlSerializer) must call the setter after the array is fully read, since the size cannot be known until fully read, and so the array cannot be allocated and set back until fully read.
(You could also do tricks with a proxy ObservableCollection, but I wouldn't recommend it.)

Iterate through properties and values of an object returned via a linq query on a domain model

I have a custom entity in a relational database that I have mapped to the CLR via a domain model. So by using the following statement, I can pull in an entity from my database into memory via a LINQ query on the domain model, like so;
var inspection = (from i in dbContext.New_testinspectionExtensionBases
where i.New_testinspectionId == currentInspection
select i).First();
There are properties/fields on this entity that I need access to, I need to be able to determine the property/field name as well as it's value. I want to loop through these items in memory, and write out their names and values to the console.
I tried using this approach, but couldn't figure out how to correct the syntax (Nor am I sure that GetProperties is the correct method to use, GetFields wasn't returning anything for some reason so I assumed this was the way to go) but it doesn't really matter since all i need is read access to the value;
var inspectionReportFields = inspection.GetType().GetProperties();
// I called this inspectionReportfields because the entity properties correspond to
// form/report fields I'm generating from this data.
foreach (var reportField in inspectionReportFields)
{
var value = reportField.GetValue();
Console.WriteLine(reportField.Name);
Console.WriteLine(value);
}
Is there an easier way to get the property/field value when utilizing a domain model like EF or openaccess? If not, am I going about it the right way? And lastly, if so, how do I fix the syntax in the value variable declaration?
Here are some sample fields/properties from the code generated by the domain model, for reference;
private int? _new_systemGauges;
public virtual int? New_systemGauges
{
get
{
return this._new_systemGauges;
}
set
{
this._new_systemGauges = value;
}
}
private int? _new_systemAlarm ;
public virtual int? New_systemAlarm
{
get
{
return this._new_systemAlarm;
}
set
{
this._new_systemAlarm = value;
}
}
I assume that you're trying to define a general-purpose way to "dump" an object without knowing anything about its structure. If so, then you are going about things the correct way. You use reflection (GetType() and the associated Type class methods) to inspect the object and return its information.
The reason GetFields() didn't return anything is that you likely did not supply the right binding flags. In particular, if you call the overload that doesn't take any parameters, you only get back public fields; if you want private fields you need to ask for them specifically.
In your case, GetFields(BindingFlags.NonPublic) would give you back the _new_systemGauges and _new_systemAlarm fields, while GetProperties() would give you back the New_systemAlarm and New_systemAlarm properties.
The other key element you missed is that the data you are getting back is the type metadata; it defines the structure of the class, and not any particular instance. If you want to know what the value of a property for a specific instance is, you need to ask for that:
foreach (var prop in obj.GetType().GetProperties())
{
Console.WriteLine("{0} = {1}", prop.Name, prop.GetValue(obj, null));
}
One you have one of the PropertyInfo elements from the type's metadata, you can ask for that property value on any instance of that type. It doesn't have to be the same instance that you originally used. For example:
var objs = somelist.Where(x => x.Id == 1);
foreach (var prop in objs.First().GetType().GetProperties())
{
int x = 0;
foreach (var obj in objs)
{
if (prop.PropertyType.Name.Equals("Int32"))
{
int val = (int)prop.GetValue(obj, null);
Console.WriteLine("Obj #{0}: {1} = 0x{2:x8}", x++, prop.Name, val);
}
else if (prop.PropertyType.Name.Equals("Decimal"))
{
int val = (decimal)prop.GetValue(obj, null);
Console.WriteLine("Obj #{0}: {1} = {2:c2}", x++, prop.Name, val);
}
else
{
Console.WriteLine("Obj #{0}: {1} = '{2}'", x++, prop.Name, prop.GetValue(obj, null));
}
}
}
Technically you should check the result of GetIndexParameters to see if a property is indexed or not; the null parameter to GetValue is actually an array of index values.
To convert the value you get back you can either use typecasts, or if you want to be a bit more flexible, use the Convert class's methods. The difference is, for example, if you have a short property, GetValue() will return a boxed short, which you cannot then typecast as an int; you have to unbox it to a short first. Using Convert.ToInt32() will perform all of the needed steps to get an int value out of any property that is convertible to an integer.
Converting between reference types is easier since you can just use is and as for that; those work just like you'd expect with "reflected" property values.
GetProperties indeed is the correct method.
To get rid of the compiler error, change your code to this:
var value = reportField.GetValue(inspection, null);
You need to pass the instance from which you want to obtain the value, as a PropertyInfo object is not bound to any specific class instance.
Please consider following the standard .NET naming rules.
This would lead to the following:
NewSystemAlarm instead of New_systemAlarm
newSystemAlarm or _newSystemAlarm instead of _new_systemAlarm
NewTestInspectionExtensionBases instead of New_testinspectionExtensionBases
NewTestInspectionId instead of New_testinspectionId
If you are using OpenAccess you always have the complete information about your model classes at your disposal. The information there is retrieved from your mapping which means that you needn't reflect over your classes (no overhead).
Just browse trough context.Metadata.PersistentTypes for all of your classes mapping information.

List<> collection members changing when they aren't supposed to

I have a List that I have populated in the main method of a console project. I pass this population to a method which is meant to take two members of the population and decompose and recombine them in a way to create two new unique members which will later be added to the population.
However when I manipulate the two original members to create the two new unique members the two original members change with in the initial population (hence altering the initial population).This means that when I go to add the new members I get duplication of entries into the List.
I'm not doing anything overly complicated I think I am just doing something stupid.
Does any one have any insight as to why this is happening ?
Here is the method that gets called to choose to initial two members of the population:
public static List<Chromosome<Gene>> runEpoch(Random rand, List<Chromosome<Gene>> population, SelectionMethod selectionMethod)
{
int populationSize = population.Count;
int selectionCount = (int)Math.Truncate((population.Count * 0.75));
if (selectionMethod == SelectionMethod.Tournament)
{
for (int i = 0; i < selectionCount; i++)
{
Chromosome<Gene> parent = selection.runTournament(rand, population);
Chromosome<Gene> parentTwo = selection.runTournament(rand, population);
//Checks for the presence of incestuous mating. In some cases incestuous mating causes a stack overflow to occur that the program can not recover from
if (parent != parentTwo)
{
//where runGeneOperators calls the crossOver method directly
offSpring = runGeneOperators(rand, parent, parentTwo);
}
else
{
i--;
}
}
}
else
{
//NSGAII
}
//fixPopulation is meant to sort and remove any excess members
return fixPopulation(rand, population, selectionMethod, populationSize); ;
}
And here is the code that is creating the two new unique members :
public List<Chromosome<Gene>> crossOver(Random rand, Chromosome<Gene> parentOne, Chromosome<Gene> parentTwo)
{
List<Chromosome<Gene>> offSpring = new List<Chromosome<Gene>>();
int crossPtOne = rand.Next(0, parentOne.Length);
int crossPtTwo = rand.Next(0, parentTwo.Length);
if ((crossPtOne == 0) && (crossPtTwo == 0))
{
offSpring.Add(parentOne);
offSpring.Add(parentTwo);
return offSpring;
}
else
{
GeneNode<Gene> fragOne = parentOne.Children[crossPtOne];
GeneNode<Gene> fragTwo = parentTwo.Children[crossPtTwo];
crossOverPoint = crossPtOne;
GeneNode<Gene> genotype = performCrossOver(parentOne.Genotype, fragTwo);
success = false;
parentOne.repair(genotype);
offSpring.Add(parentOne);
crossOverPoint = crossPtTwo;
GeneNode<Gene> genotype2 = performCrossOver(parentTwo.Genotype, fragOne);
success = false;
parentTwo.repair(genotype2);
offSpring.Add(parentTwo);
}
return offSpring;
}
private GeneNode<Gene> performCrossOver(GeneNode<Gene> tree, GeneNode<Gene> frag)
{
if (tree != null)
{
if (crossOverPoint > 0)
{
if (!success && tree.Left != null)
{
crossOverPoint--;
tree.Children[0] = performCrossOver(tree.Left, frag);
}
}
if (crossOverPoint > 0)
{
if (!success && tree.Right != null)
{
crossOverPoint--;
tree.Children[1] = performCrossOver(tree.Right, frag);
}
}
}
if (!success)
{
if (crossOverPoint == 0)
{
success = true;
return frag;
}
}
return tree;
}
In C#, objects are reference types, meaning adding something to a collection only adds a reference. If you manipulate a variable with the same reference (in your case, the "original" objects), all references pointing to that object will be changed as well. You need to copy the object somehow to have a different object and manipulate that.
To manipulate your collection and objects within it without altering it, you need to do a deep clone of the collection and it's containing objects, so you can alter list A without altering clone B. If you just wish to change some object inside the list you need to make a deep clone of the object inside the list and then alter the deep clone. This will make sure that your original is not altered.
The IClonable interface should be implemented on your objects to make them clonable.
EDIT: Per Henk's Comments, you should just implement your own copy method without implementing the IClonable interface, as per this article.
Cloning of objects comes in two forms, deep and shallow.
Shallow: This form of cloning creates a new object and then copyies the nonstatic fields of the current object to the new object. If a field is a value type, a bit-by-bit copy of the field is performed. If a field is a reference type, the reference is copied but the referred object is not; therefore, the original object and its clone refer to the same object.
Deep:This creates a new object and clones all data members and fields of the clonable object. This object references X2 where the original will reference X.
Here a post from SO that might assist you in cloning.
Item 1 - Keep your list references private
From a API perspective, an object should never give out the reference to its internal list. This is due to the issue you have just found, whereby some other consumer code can go ahead and modify that list as it sees fit. Every reference of that list, as shared around, including the 'owning' object, has their list updated. This is usually not what was intended.
Further, the responsibility is not on the consumer to make its own copy. The responsibility is on the owner of the list to keep its version private.
It's easy enough to create a new List
private List<Gene> initialGeneList;
public List<Gene> InitialGenes
{
get { return new List<Gene>(initialGeneList); } // return a new list
}
This advice also includes passing your own list to another class/method.
Item 2 - Consider using an immutable object
Without going too much into reference vs value types, what this means is treat the object like a value type, and whenever you have an operation, return a new object instead of mutating the original.
Real value types in .net, like integers and DateTimes have the semantic of copy on assignment. e.g. When you assign, a copy is created.
Reference types can also behave like value types, and strings are good example. Many people make the following mistake, because they fail to realize the value-type semantics of System.String.
string s = "Hello World";
s.Substring(0,5); // s unchanged. still 'Hello World'
s = s.Substring(0,5); // s changed. now 'Hello'
The string method Substring() doesn't mutate the original object, but instead returns a new one containing the result of the operation.
Where appropriate, the use of immutable objects can make the program a lot easier to understand and can reduce defects considerably.
When implementing immutable objects, one caveat is the likely need to implement value equality for comparing two objects (by overriding Equals). Objects are reference types, and by default two objects are equal if their references are equal.
In this snippet, the values of the objects are equal, but they are different objects.
string s1 = "Hello";
string s2 = string.Concat("He","l", "lo");
bool equal = s1.Equals(s2);
bool referenceEqual = object.ReferenceEquals(s1, s2);
// s1 == s2 => True, Reference Equal => False
Console.Write("s1 == s2 => {0}, Reference Equal => {1}", equal, referenceEqual);

Categories