Skip to content

[AI Task] [Tizen.Pims.Contacts] Remove Convert.ChangeType boxing from ContactsRecord Get/Set - #7762

Open
JoonghyunCho wants to merge 2 commits into
mainfrom
ai-task/issue-7667
Open

[AI Task] [Tizen.Pims.Contacts] Remove Convert.ChangeType boxing from ContactsRecord Get/Set#7762
JoonghyunCho wants to merge 2 commits into
mainfrom
ai-task/issue-7667

Conversation

@JoonghyunCho

Copy link
Copy Markdown
Member

Summary

Removes the Convert.ChangeType / Convert.To* conversion paths from ContactsRecord.Get<T>(uint) and Set<T>(uint, T). Each branch already verifies the exact type via typeof(T) == typeof(X), so the value is converted with a direct cast ((T)(object)val) instead of going through the culture-aware IConvertible dispatch. Get<T> also drops the intermediate object parsedValue local and returns directly from each branch.

Per-call effect (e.g. Get<int>): no Convert.ChangeType call, no IConvertible vtable dispatch, no CultureInfo lookup. For Get<string>/Set<string> the boxing allocation disappears entirely (reference-type cast). ContactsRecord property access is the per-field unit of contact serialization, so bulk sync/import workloads (10k records × ~10 properties) save hundreds of thousands of dispatch/boxing operations.

Changes

  • src/Tizen.Pims.Contacts/Tizen.Pims.Contacts/ContactsRecord.cs
    • Get<T>: each type branch now ends with return (T)(object)val;; removed object parsedValue local, Convert.ChangeType calls (5), and the trailing unbox return (T)parsedValue;. Unsupported-type branch still throws NotSupported as before.
    • Set<T>: Convert.ToString/ToInt32/ToBoolean/ToInt64/ToDouble replaced with direct casts. The string branch uses (string)(object)value ?? string.Empty to preserve the exact prior behavior of Convert.ToString(object), which maps null to string.Empty (so native SetStr still receives an empty string, not null).

Mode

Refactoring

Verification

  • Build: passed (0 errors, 0 warnings)
  • Tests: N/A
  • Benchmark: skipped (sdb error: no device connected)

Public API signatures (T Get<T>(uint), void Set<T>(uint, T)) are unchanged. Every direct cast is guarded by the exact typeof(T) check, so no InvalidCastException is reachable on paths that previously succeeded; normal-path results are bit-identical, including Get<string> returning null when the native value is NULL.

Fixes #7667

🤖 Generated with Claude Code

…actsRecord Get/Set (Fixes #7667)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@JoonghyunCho

Copy link
Copy Markdown
Member Author

Benchmark skipped: no sdb device is connected in the CI/bot environment (sdb devices returned an empty list), so the comparative benchmark could not be deployed or run. Manual benchmark verification is required. Expected direction is strictly non-regressive: the change removes Convert.ChangeType/IConvertible dispatch and CultureInfo lookups from every Get/Set call and eliminates the boxing allocation on the Get/Set paths.

@github-actions github-actions Bot added the API15 label Jul 19, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the generic Get<T> and Set<T> methods in ContactsRecord.cs to replace Convert helper methods with direct casting, which simplifies the code and avoids unnecessary conversion overhead. The reviewer suggested a more idiomatic C# approach for the string conversion in Set<T> by using the as operator directly on the generic parameter instead of casting it to object first.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

if (typeof(T) == typeof(string))
{
string val = Convert.ToString(value);
string val = (string)(object)value ?? string.Empty;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Since string is a reference type, you can use the as operator directly on the generic parameter value without needing to cast it to object first. This is more idiomatic and readable in C#.

                string val = value as string ?? string.Empty;

@@ -255,14 +254,13 @@ public T Get<T>(uint propertyId)
Log.Error(Globals.LogTag, $"Get Long Failed with error {error}");

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 [AI Review]
🟡 Suggestion: Pre-existing copy-paste in this double branch logs "Get Long Failed"; since this PR already rewrites these branches, it is worth fixing here (the Set double branch at line 323 has the same "Get Long" text).

Suggested change
Log.Error(Globals.LogTag, $"Get Long Failed with error {error}");
Log.Error(Globals.LogTag, $"Get Double Failed with error {error}");

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 [AI Review]
Addressed in 3aa053e — the Get double branch now logs "Get Double Failed" and the Set double branch logs "Set Double Failed".

Fix copy-paste log messages in the double branches of Get<T>/Set<T> and use 'as' cast for the string path in Set<T>

Applied-Human-Comments: 3610427947
Applied-AI-Comments: 3611527170
@JoonghyunCho

Copy link
Copy Markdown
Member Author

🤖 [AI Review]
Addressed review feedback in commit 3aa053e. Summary: replaced the (string)(object) double cast with an idiomatic as cast in Set (per gemini-code-assist), and fixed the copy-paste "Get Long Failed" log messages in the Get/Set double branches.

@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@TizenAPI-Bot

Copy link
Copy Markdown
Collaborator

Public API Changed

Please follow the ACR process for the changed API below.

Added: 0, Removed: 43, Changed: 0

Removed

- /// <since_tizen>4</since_tizen
- [Obsolete]
- Tizen.Applications.AttachPanel.AttachPanel

- /// <privilege>http://tizen.org/feature/attach_panel</privilege
- /// <since_tizen>4</since_tizen
- [Obsolete]
- System.Boolean Tizen.Applications.AttachPanel.AttachPanel::Visible()

- /// <privilege>http://tizen.org/feature/attach_panel</privilege
- /// <since_tizen>4</since_tizen
- [Obsolete]
- Tizen.Applications.AttachPanel.StateType Tizen.Applications.AttachPanel.AttachPanel::State()

- /// <privilege>http://tizen.org/feature/attach_panel</privilege
- /// <since_tizen>4</since_tizen
- [Obsolete]
- System.Void Tizen.Applications.AttachPanel.AttachPanel::.ctor(ElmSharp.Conformant)

- /// <privilege>http://tizen.org/feature/attach_panel</privilege
- /// <since_tizen>4</since_tizen
- [Obsolete]
- System.Void Tizen.Applications.AttachPanel.AttachPanel::.ctor(ElmSharp.EvasObject)

- /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege
- /// <privilege>http://tizen.org/privilege/camera</privilege
- /// <privilege>http://tizen.org/privilege/mediastorage</privilege
- /// <privilege>http://tizen.org/privilege/recorder</privilege
- /// <privilege>http://tizen.org/privilege/telephony</privilege
- /// <privilege>http://tizen.org/feature/attach_panel</privilege
- /// <privilege>http://tizen.org/feature/camera</privilege
- /// <privilege>http://tizen.org/feature/microphone</privilege
- /// <since_tizen>4</since_tizen
- [Obsolete]
- System.Void Tizen.Applications.AttachPanel.AttachPanel::AddCategory(Tizen.Applications.AttachPanel.ContentCategory,Tizen.Applications.Bundle)

- /// <since_tizen>none</since_tizen
- System.Void Tizen.Applications.AttachPanel.AttachPanel::Finalize()

- /// <privilege>http://tizen.org/feature/attach_panel</privilege
- /// <since_tizen>4</since_tizen
- [Obsolete]
- System.Void Tizen.Applications.AttachPanel.AttachPanel::Hide()

- /// <privilege>http://tizen.org/feature/attach_panel</privilege
- /// <since_tizen>4</since_tizen
- [Obsolete]
- System.Void Tizen.Applications.AttachPanel.AttachPanel::Hide(System.Boolean)

- /// <privilege>http://tizen.org/feature/attach_panel</privilege
- /// <since_tizen>4</since_tizen
- [Obsolete]
- System.Void Tizen.Applications.AttachPanel.AttachPanel::RemoveCategory(Tizen.Applications.AttachPanel.ContentCategory)

- /// <privilege>http://tizen.org/feature/attach_panel</privilege
- /// <since_tizen>4</since_tizen
- [Obsolete]
- System.Void Tizen.Applications.AttachPanel.AttachPanel::SetExtraData(Tizen.Applications.AttachPanel.ContentCategory,Tizen.Applications.Bundle)

- /// <privilege>http://tizen.org/feature/attach_panel</privilege
- /// <since_tizen>4</since_tizen
- [Obsolete]
- System.Void Tizen.Applications.AttachPanel.AttachPanel::Show()

- /// <privilege>http://tizen.org/feature/attach_panel</privilege
- /// <since_tizen>4</since_tizen
- [Obsolete]
- System.Void Tizen.Applications.AttachPanel.AttachPanel::Show(System.Boolean)

- /// <since_tizen>4</since_tizen
- [Obsolete]
- System.EventHandler`1<Tizen.Applications.AttachPanel.ResultEventArgs> Tizen.Applications.AttachPanel.AttachPanel::ResultCallback

- /// <since_tizen>4</since_tizen
- [Obsolete]
- System.EventHandler`1<Tizen.Applications.AttachPanel.StateEventArgs> Tizen.Applications.AttachPanel.AttachPanel::EventChanged

- /// <since_tizen>4</since_tizen
- [Obsolete]
- Tizen.Applications.AttachPanel.ContentCategory

- /// <since_tizen>none</since_tizen
- static Tizen.Applications.AttachPanel.ContentCategory Tizen.Applications.AttachPanel.ContentCategory::Audio

- /// <since_tizen>none</since_tizen
- static Tizen.Applications.AttachPanel.ContentCategory Tizen.Applications.AttachPanel.ContentCategory::Calendar

- /// <since_tizen>none</since_tizen
- static Tizen.Applications.AttachPanel.ContentCategory Tizen.Applications.AttachPanel.ContentCategory::Camera

- /// <since_tizen>none</since_tizen
- static Tizen.Applications.AttachPanel.ContentCategory Tizen.Applications.AttachPanel.ContentCategory::Contact

- /// <since_tizen>none</since_tizen
- static Tizen.Applications.AttachPanel.ContentCategory Tizen.Applications.AttachPanel.ContentCategory::Document

- /// <since_tizen>none</since_tizen
- static Tizen.Applications.AttachPanel.ContentCategory Tizen.Applications.AttachPanel.ContentCategory::Image

- /// <since_tizen>none</since_tizen
- static Tizen.Applications.AttachPanel.ContentCategory Tizen.Applications.AttachPanel.ContentCategory::Memo

- /// <since_tizen>none</since_tizen
- static Tizen.Applications.AttachPanel.ContentCategory Tizen.Applications.AttachPanel.ContentCategory::Myfiles

- /// <since_tizen>none</since_tizen
- static Tizen.Applications.AttachPanel.ContentCategory Tizen.Applications.AttachPanel.ContentCategory::TakePicture

- /// <since_tizen>none</since_tizen
- static Tizen.Applications.AttachPanel.ContentCategory Tizen.Applications.AttachPanel.ContentCategory::Video

- /// <since_tizen>none</since_tizen
- static Tizen.Applications.AttachPanel.ContentCategory Tizen.Applications.AttachPanel.ContentCategory::VideoRecorder

- /// <since_tizen>none</since_tizen
- static Tizen.Applications.AttachPanel.ContentCategory Tizen.Applications.AttachPanel.ContentCategory::Voice

- /// <since_tizen>4</since_tizen
- [Obsolete]
- Tizen.Applications.AttachPanel.EventType

- /// <since_tizen>none</since_tizen
- static Tizen.Applications.AttachPanel.EventType Tizen.Applications.AttachPanel.EventType::HideFinish

- /// <since_tizen>none</since_tizen
- static Tizen.Applications.AttachPanel.EventType Tizen.Applications.AttachPanel.EventType::HideStart

- /// <since_tizen>none</since_tizen
- static Tizen.Applications.AttachPanel.EventType Tizen.Applications.AttachPanel.EventType::ShowFinish

- /// <since_tizen>none</since_tizen
- static Tizen.Applications.AttachPanel.EventType Tizen.Applications.AttachPanel.EventType::ShowStart

- /// <since_tizen>4</since_tizen
- [Obsolete]
- Tizen.Applications.AttachPanel.ResultEventArgs

- /// <since_tizen>4</since_tizen
- [Obsolete]
- Tizen.Applications.AppControl Tizen.Applications.AttachPanel.ResultEventArgs::Result()

- /// <since_tizen>4</since_tizen
- [Obsolete]
- Tizen.Applications.AppControlReplyResult Tizen.Applications.AttachPanel.ResultEventArgs::ResultCode()

- /// <since_tizen>4</since_tizen
- [Obsolete]
- Tizen.Applications.AttachPanel.ContentCategory Tizen.Applications.AttachPanel.ResultEventArgs::Category()

- /// <since_tizen>4</since_tizen
- [Obsolete]
- Tizen.Applications.AttachPanel.StateEventArgs

- /// <since_tizen>4</since_tizen
- [Obsolete]
- Tizen.Applications.AttachPanel.EventType Tizen.Applications.AttachPanel.StateEventArgs::EventType()

- /// <since_tizen>4</since_tizen
- [Obsolete]
- Tizen.Applications.AttachPanel.StateType

- /// <since_tizen>none</since_tizen
- static Tizen.Applications.AttachPanel.StateType Tizen.Applications.AttachPanel.StateType::Full

- /// <since_tizen>none</since_tizen
- static Tizen.Applications.AttachPanel.StateType Tizen.Applications.AttachPanel.StateType::Hidden

- /// <since_tizen>none</since_tizen
- static Tizen.Applications.AttachPanel.StateType Tizen.Applications.AttachPanel.StateType::Partial

Internal API Changed

Added: 1, Removed: 0, Changed: 0

Added

+ /// <since_tizen>none</since_tizen
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ System.Void Tizen.NUI.BaseComponents.LottieAnimationView::RefreshDynamicProperty()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

2 participants