in compiler/cpp/src/thrift/generate/t_netstd_generator.cc [1655:1852]
void t_netstd_generator::generate_netstd_union_definition(ostream& out, t_struct* tunion)
{
// Let's define the class first
start_netstd_namespace(out);
generate_deprecation_attribute(out, tunion->annotations_);
out << indent() << "public abstract partial class " << normalize_name(tunion->get_name()) << " : TUnionBase" << '\n';
out << indent() << "{" << '\n';
indent_up();
out << indent() << "public abstract global::System.Threading.Tasks.Task WriteAsync(TProtocol tProtocol, CancellationToken " << CANCELLATION_TOKEN_NAME << ");" << '\n'
<< indent() << "public readonly int Isset;" << '\n'
<< indent() << "public abstract object" << nullable_suffix() <<" Data { get; }" << '\n'
<< indent() << "protected " << normalize_name(tunion->get_name()) << "(int isset)" << '\n'
<< indent() << "{" << '\n';
indent_up();
out << indent() << "Isset = isset;" << '\n';
indent_down();
out << indent() << "}" << '\n' << '\n';
const vector<t_field*>& fields = tunion->get_members();
vector<t_field*>::const_iterator f_iter;
out << indent() << "public override bool Equals(object" << nullable_suffix() << " that)" << '\n';
scope_up(out);
if( target_net_version >= 6) {
out << indent() << "if (that is not " << tunion->get_name() << " other) return false;" << '\n';
} else {
out << indent() << "if (!(that is " << tunion->get_name() << " other)) return false;" << '\n';
}
out << indent() << "if (ReferenceEquals(this, other)) return true;" << '\n';
out << '\n';
out << indent() << "if(this.Isset != other.Isset) return false;" << '\n';
out << '\n';
if(target_net_version >= 6) {
out << indent() << "return Isset switch" << '\n';
scope_up(out);
for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter)
{
bool needs_typecast = false;
string suffix("");
get_deep_copy_method_call((*f_iter)->get_type(), false, needs_typecast, suffix);
out << indent() << (*f_iter)->get_key() << " => Equals(As_" << (*f_iter)->get_name() << ", other.As_" << (*f_iter)->get_name() << ")," << '\n';
}
out << indent() << "_ => true," << '\n';
indent_down();
out << indent() << "};" << '\n';
} else {
out << indent() << "switch (Isset)" << '\n';
scope_up(out);
for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter)
{
bool needs_typecast = false;
string suffix("");
get_deep_copy_method_call((*f_iter)->get_type(), false, needs_typecast, suffix);
out << indent() << "case " << (*f_iter)->get_key() << ":" << '\n';
indent_up();
out << indent() << "return Equals(As_" << (*f_iter)->get_name() << ", other.As_" << (*f_iter)->get_name() << ");" << '\n';
indent_down();
}
out << indent() << "default:" << '\n';
indent_up();
out << indent() << "return true;" << '\n';
indent_down();
scope_down(out);
}
scope_down(out);
out << '\n';
out << indent() << "public override int GetHashCode()" << '\n';
out << indent() << "{" << '\n';
indent_up();
if(target_net_version >= 6) {
out << indent() << "return Isset switch" << '\n';
out << indent() << "{" << '\n';
indent_up();
for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter)
{
string null_coalesce(is_nullable_type((*f_iter)->get_type()) ? "?" : "");
out << indent() << (*f_iter)->get_key() << " => As_" << (*f_iter)->get_name() << null_coalesce << ".GetHashCode()";
if( null_coalesce.size() > 0) {
out << " ?? 0";
}
out << "," << '\n';
}
out << indent() << "_ => (new ___undefined()).GetHashCode()" << '\n';
indent_down();
out << indent() << "};" << '\n';
} else {
out << indent() << "switch (Isset)" << '\n';
out << indent() << "{" << '\n';
indent_up();
for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter)
{
string null_coalesce(is_nullable_type((*f_iter)->get_type()) ? "?" : "");
out << indent() << "case " << (*f_iter)->get_key() << ":" << '\n';
indent_up();
out << indent() << "return As_" << (*f_iter)->get_name() << null_coalesce << ".GetHashCode()";
if( null_coalesce.size() > 0) {
out << " ?? 0";
}
out << ";" << '\n';
indent_down();
}
out << indent() << "default:" << '\n';
indent_up();
out << indent() << "return (new ___undefined()).GetHashCode();" << '\n';
indent_down();
indent_down();
out << indent() << "}" << '\n';
}
indent_down();
out << indent() << "}" << '\n' << '\n';
if( ! suppress_deepcopy) {
out << indent() << "public " << tunion->get_name() << " " << DEEP_COPY_METHOD_NAME << "()" << '\n';
out << indent() << "{" << '\n';
indent_up();
if(target_net_version >= 6) {
out << indent() << "return Isset switch" << '\n';
out << indent() << "{" << '\n';
indent_up();
for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter)
{
bool needs_typecast = false;
string suffix("");
string copy_op = get_deep_copy_method_call((*f_iter)->get_type(), false, needs_typecast, suffix);
out << indent() << (*f_iter)->get_key() << " => new " << (*f_iter)->get_name() << "(As_" << (*f_iter)->get_name() << suffix << copy_op << ")," << '\n';
}
out << indent() << "_ => new ___undefined()" << '\n';
indent_down();
out << indent() << "};" << '\n';
} else {
out << indent() << "switch (Isset)" << '\n';
out << indent() << "{" << '\n';
indent_up();
for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter)
{
bool needs_typecast = false;
string suffix("");
string copy_op = get_deep_copy_method_call((*f_iter)->get_type(), false, needs_typecast, suffix);
out << indent() << "case " << (*f_iter)->get_key() << ":" << '\n';
indent_up();
out << indent() << "return new " << (*f_iter)->get_name() << "(As_" << (*f_iter)->get_name() << suffix << copy_op << ");" << '\n';
indent_down();
}
out << indent() << "default:" << '\n';
indent_up();
out << indent() << "return new ___undefined();" << '\n';
indent_down();
indent_down();
out << indent() << "}" << '\n';
}
indent_down();
out << indent() << "}" << '\n' << '\n';
}
out << indent() << "public class ___undefined : " << tunion->get_name() << '\n';
out << indent() << "{" << '\n';
indent_up();
out << indent() << "public override object" << nullable_suffix() <<" Data { get { return null; } }" << '\n'
<< indent() << "public ___undefined() : base(0) {}" << '\n' << '\n';
if( ! suppress_deepcopy) {
out << indent() << "public new ___undefined " << DEEP_COPY_METHOD_NAME << "()" << '\n';
out << indent() << "{" << '\n';
indent_up();
out << indent() << "return new ___undefined();" << '\n';
indent_down();
out << indent() << "}" << '\n' << '\n';
}
t_struct undefined_struct(program_,"___undefined");
generate_netstd_struct_equals(out, &undefined_struct);
generate_netstd_struct_hashcode(out, &undefined_struct);
out << indent() << "public override global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken " << CANCELLATION_TOKEN_NAME << ")" << '\n'
<< indent() << "{" << '\n';
indent_up();
out << indent() << "throw new TProtocolException( TProtocolException.INVALID_DATA, \"Cannot persist an union type which is not set.\");" << '\n';
indent_down();
out << indent() << "}" << '\n' << '\n';
indent_down();
out << indent() << "}" << '\n' << '\n';
for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter)
{
generate_netstd_union_class(out, tunion, (*f_iter));
}
generate_netstd_union_reader(out, tunion);
indent_down();
out << indent() << "}" << '\n' << '\n';
end_netstd_namespace(out);
}