Skip to content
2 changes: 1 addition & 1 deletion Ical.Net.Tests/RecurrenceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3904,7 +3904,7 @@ public void TestDtStartTimezone(string? tzId)
var cal = Calendar.Load(icalText);
var evt = cal.Events.First();
var ev = new EventEvaluator(evt);
var occurrences = ev.Evaluate(evt.DtStart, evt.DtStart.ToTimeZone(tzId), evt.DtStart.AddMinutes(61).ToTimeZone(tzId), default);
var occurrences = ev.Evaluate(evt.DtStart, evt.DtStart.ToTimeZone(tzId), evt.DtStart.AddMinutes(61).ToTimeZone(tzId), null);
var occurrencesStartTimes = occurrences.Select(x => x.StartTime).Take(2).ToList();

var expectedStartTimes = new[]
Expand Down
14 changes: 11 additions & 3 deletions Ical.Net/CalendarComponents/Alarm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@
/// since the provided <paramref name="start"/> date/time. If <paramref name="start"/>
/// is null, all triggered alarms will be returned.
/// </summary>
/// <param name="start">The earliest date/time to poll trigered alarms for.</param>
/// <param name="start">The earliest date/time to poll triggered alarms for.</param>
/// <param name="end"></param>
/// <param name="options"></param>
/// <returns>A list of <see cref="AlarmOccurrence"/> objects, each containing a triggered alarm.</returns>
Expand Down Expand Up @@ -171,12 +171,20 @@
for (var i = 0; i < len; i++)
{
var ao = occurrences[i];
if (ao?.DateTime == null || ao.Component == null)
{
continue;
}

var alarmTime = ao.DateTime.Copy();

for (var j = 0; j < Repeat; j++)
{
alarmTime = alarmTime.Add(Duration);
occurrences.Add(new AlarmOccurrence(this, alarmTime.Copy(), ao.Component));
alarmTime = alarmTime?.Add(Duration);

Check warning on line 183 in Ical.Net/CalendarComponents/Alarm.cs

View check run for this annotation

Codecov / codecov/patch

Ical.Net/CalendarComponents/Alarm.cs#L183

Added line #L183 was not covered by tests
if (alarmTime != null)
{
occurrences.Add(new AlarmOccurrence(this, alarmTime.Copy(), ao.Component));

Check warning on line 186 in Ical.Net/CalendarComponents/Alarm.cs

View check run for this annotation

Codecov / codecov/patch

Ical.Net/CalendarComponents/Alarm.cs#L186

Added line #L186 was not covered by tests
}
}
}
}
Expand Down
22 changes: 14 additions & 8 deletions Ical.Net/DataTypes/AlarmOccurrence.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// Licensed under the MIT license.
//

#nullable enable
using System;
using Ical.Net.CalendarComponents;

Expand All @@ -18,16 +19,16 @@
/// </remarks>
public class AlarmOccurrence : IComparable<AlarmOccurrence>
{
public Period Period { get; set; }
public Period? Period { get; set; }

public IRecurringComponent Component { get; set; }
public IRecurringComponent? Component { get; set; }

public Alarm Alarm { get; set; }
public Alarm? Alarm { get; set; }

public CalDateTime DateTime
public CalDateTime? DateTime
{
get => Period.StartTime;
set => Period = new Period(value);
get => Period?.StartTime;
set => Period = value != null ? new Period(value) : null;

Check warning on line 31 in Ical.Net/DataTypes/AlarmOccurrence.cs

View check run for this annotation

Codecov / codecov/patch

Ical.Net/DataTypes/AlarmOccurrence.cs#L31

Added line #L31 was not covered by tests
}

public AlarmOccurrence(AlarmOccurrence ao)
Expand All @@ -44,14 +45,19 @@
Component = rc;
}

public int CompareTo(AlarmOccurrence other) => Period.CompareTo(other.Period);
public int CompareTo(AlarmOccurrence? other)
Copy link

Copilot AI Apr 7, 2025

Choose a reason for hiding this comment

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

[nitpick] In the CompareTo method, returning 1 when other or its Period is null could result in inconsistent ordering; consider defining explicit ordering when both Period properties are null.

Copilot uses AI. Check for mistakes.
{
if (other == null) return 1;
if (Period == null) return other.Period == null ? 0 : -1;
return Period.CompareTo(other.Period);

Check warning on line 52 in Ical.Net/DataTypes/AlarmOccurrence.cs

View check run for this annotation

Codecov / codecov/patch

Ical.Net/DataTypes/AlarmOccurrence.cs#L52

Added line #L52 was not covered by tests
}

protected bool Equals(AlarmOccurrence other)
=> Equals(Period, other.Period)
&& Equals(Component, other.Component)
&& Equals(Alarm, other.Alarm);

public override bool Equals(object obj)
public override bool Equals(object? obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
Expand Down
27 changes: 17 additions & 10 deletions Ical.Net/DataTypes/Attachment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// Licensed under the MIT license.
//

#nullable enable
using System;
using System.Linq;
using System.Text;
Expand All @@ -18,8 +19,8 @@
/// </summary>
public class Attachment : EncodableDataType
{
public virtual Uri Uri { get; set; }
public virtual byte[] Data { get; private set; } // private set for CopyFrom
public virtual Uri? Uri { get; set; }
public virtual byte[]? Data { get; private set; } // private set for CopyFrom

private Encoding _valueEncoding = System.Text.Encoding.UTF8;
public virtual Encoding ValueEncoding
Expand All @@ -43,7 +44,7 @@

public Attachment() { }

public Attachment(byte[] value) : this()
public Attachment(byte[]? value) : this()
{
if (value != null)
{
Expand Down Expand Up @@ -93,15 +94,21 @@
FormatType = att.FormatType;
}

protected bool Equals(Attachment other)
protected bool Equals(Attachment? other)
{
var firstPart = Equals(Uri, other.Uri) && ValueEncoding.Equals(other.ValueEncoding);
return Data == null
? firstPart
: firstPart && Data.SequenceEqual(other.Data);
var firstPart = Equals(Uri, other?.Uri) && ValueEncoding.Equals(other?.ValueEncoding);
if (Data == null && other?.Data == null)
{
return firstPart;
}
if (Data == null || other?.Data == null)
{
return false;

Check warning on line 106 in Ical.Net/DataTypes/Attachment.cs

View check run for this annotation

Codecov / codecov/patch

Ical.Net/DataTypes/Attachment.cs#L106

Added line #L106 was not covered by tests
}
return firstPart && Data.SequenceEqual(other.Data);
}

public override bool Equals(object obj)
public override bool Equals(object? obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
Expand All @@ -118,4 +125,4 @@
return hashCode;
}
}
}
}
41 changes: 16 additions & 25 deletions Ical.Net/DataTypes/Attendee.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// Licensed under the MIT license.
//

#nullable enable
using System;
using System.Collections.Generic;
using System.Linq;
Expand All @@ -12,9 +13,9 @@

public class Attendee : EncodableDataType
{
private Uri _sentBy;
private Uri? _sentBy;
/// <summary> SENT-BY, to indicate who is acting on behalf of the ATTENDEE </summary>
public virtual Uri SentBy
public virtual Uri? SentBy
{
get
{
Expand All @@ -38,7 +39,7 @@
}
}

private string _commonName;
private string? _commonName;
/// <summary> CN: to show the common or displayable name associated with the calendar address </summary>
public virtual string CommonName
{
Expand All @@ -48,7 +49,7 @@
{
_commonName = Parameters.Get("CN");
}
return _commonName;

Check warning on line 52 in Ical.Net/DataTypes/Attendee.cs

View workflow job for this annotation

GitHub Actions / coverage

Possible null reference return.

Check warning on line 52 in Ical.Net/DataTypes/Attendee.cs

View workflow job for this annotation

GitHub Actions / coverage

Possible null reference return.

Check warning on line 52 in Ical.Net/DataTypes/Attendee.cs

View workflow job for this annotation

GitHub Actions / tests

Possible null reference return.

Check warning on line 52 in Ical.Net/DataTypes/Attendee.cs

View workflow job for this annotation

GitHub Actions / tests

Possible null reference return.
}
set
{
Expand All @@ -61,9 +62,9 @@
}
}

private Uri _directoryEntry;
private Uri? _directoryEntry;
/// <summary> DIR, to indicate the URI that points to the directory information corresponding to the attendee </summary>
public virtual Uri DirectoryEntry
public virtual Uri? DirectoryEntry
{
get
{
Expand All @@ -87,7 +88,7 @@
}
}

private string _type;
private string? _type;
/// <summary> CUTYPE: the type of calendar user </summary>
public virtual string Type
{
Expand All @@ -97,7 +98,7 @@
{
_type = Parameters.Get("CUTYPE");
}
return _type;

Check warning on line 101 in Ical.Net/DataTypes/Attendee.cs

View workflow job for this annotation

GitHub Actions / coverage

Possible null reference return.

Check warning on line 101 in Ical.Net/DataTypes/Attendee.cs

View workflow job for this annotation

GitHub Actions / coverage

Possible null reference return.

Check warning on line 101 in Ical.Net/DataTypes/Attendee.cs

View workflow job for this annotation

GitHub Actions / tests

Possible null reference return.

Check warning on line 101 in Ical.Net/DataTypes/Attendee.cs

View workflow job for this annotation

GitHub Actions / tests

Possible null reference return.
}
set
{
Expand All @@ -111,7 +112,7 @@
}
}

private List<string> _members;
private List<string>? _members;
/// <summary> MEMBER: the groups the user belongs to </summary>
public virtual IList<string> Members
{
Expand All @@ -123,7 +124,7 @@
}
}

private string _role;
private string? _role;
/// <summary> ROLE: the intended role the attendee will have </summary>
public virtual string Role
{
Expand All @@ -133,7 +134,7 @@
{
_role = Parameters.Get("ROLE");
}
return _role;

Check warning on line 137 in Ical.Net/DataTypes/Attendee.cs

View workflow job for this annotation

GitHub Actions / coverage

Possible null reference return.

Check warning on line 137 in Ical.Net/DataTypes/Attendee.cs

View workflow job for this annotation

GitHub Actions / tests

Possible null reference return.

Check warning on line 137 in Ical.Net/DataTypes/Attendee.cs

View workflow job for this annotation

GitHub Actions / tests

Possible null reference return.
}
set
{
Expand All @@ -146,7 +147,7 @@
}
}

private string _participationStatus;
private string? _participationStatus;
public virtual string ParticipationStatus
{
get
Expand All @@ -155,7 +156,7 @@
{
_participationStatus = Parameters.Get(EventParticipationStatus.Key);
}
return _participationStatus;

Check warning on line 159 in Ical.Net/DataTypes/Attendee.cs

View workflow job for this annotation

GitHub Actions / coverage

Possible null reference return.

Check warning on line 159 in Ical.Net/DataTypes/Attendee.cs

View workflow job for this annotation

GitHub Actions / tests

Possible null reference return.

Check warning on line 159 in Ical.Net/DataTypes/Attendee.cs

View workflow job for this annotation

GitHub Actions / tests

Possible null reference return.
}
set
{
Expand All @@ -179,9 +180,8 @@
return _rsvp.Value;
}

bool val;
var rsvp = Parameters.Get("RSVP");
if (rsvp != null && bool.TryParse(rsvp, out val))
if (rsvp != null && bool.TryParse(rsvp, out var val))
{
_rsvp = val;
return _rsvp.Value;
Expand All @@ -196,40 +196,32 @@
}
}

private List<string> _delegatedTo;
private List<string>? _delegatedTo;
/// <summary> DELEGATED-TO, to indicate the calendar users that the original request was delegated to </summary>
public virtual IList<string> DelegatedTo
{
get => _delegatedTo ?? (_delegatedTo = new List<string>(Parameters.GetMany("DELEGATED-TO")));
set
{
if (value == null)
{
return;
}
_delegatedTo = new List<string>(value);
Parameters.Set("DELEGATED-TO", value);
}
}

private List<string> _delegatedFrom;
private List<string>? _delegatedFrom;
/// <summary> DELEGATED-FROM, to indicate whom the request was delegated from </summary>
public virtual IList<string> DelegatedFrom
{
get => _delegatedFrom ?? (_delegatedFrom = new List<string>(Parameters.GetMany("DELEGATED-FROM")));
set
{
if (value == null)
{
return;
}
_delegatedFrom = new List<string>(value);
Parameters.Set("DELEGATED-FROM", value);
}
}

/// <summary> Uri associated with the attendee, typically an email address </summary>
public virtual Uri Value { get; set; }
public virtual Uri? Value { get; set; }

public Attendee() { }

Expand Down Expand Up @@ -278,8 +270,7 @@
&& Members.SequenceEqual(other.Members)
&& DelegatedTo.SequenceEqual(other.DelegatedTo)
&& DelegatedFrom.SequenceEqual(other.DelegatedFrom);

public override bool Equals(object obj)
public override bool Equals(object? obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
Expand All @@ -305,4 +296,4 @@
return hashCode;
}
}
}
}
24 changes: 13 additions & 11 deletions Ical.Net/DataTypes/CalendarDataType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// Licensed under the MIT license.
//

#nullable enable
using System;
using System.Runtime.Serialization;
using Ical.Net.Proxies;
Expand All @@ -14,10 +15,11 @@ namespace Ical.Net.DataTypes;
/// </summary>
public abstract class CalendarDataType : ICalendarDataType
{
private IParameterCollection _parameters;
private ParameterCollectionProxy _proxy;
// Well be set with Initialize()
private IParameterCollection _parameters = null!;
private ParameterCollectionProxy _proxy = null!;

private ICalendarObject _associatedObject;
private ICalendarObject? _associatedObject;

protected CalendarDataType()
{
Expand Down Expand Up @@ -49,10 +51,10 @@ protected virtual void OnDeserializing(StreamingContext context)

protected virtual void OnDeserialized(StreamingContext context) { }

public virtual Type GetValueType()
public virtual Type? GetValueType()
{
// See RFC 5545 Section 3.2.20.
if (_proxy != null && _proxy.ContainsKey("VALUE"))
if (_proxy.ContainsKey("VALUE"))
{
switch (_proxy.Get("VALUE"))
{
Expand Down Expand Up @@ -92,12 +94,12 @@ public virtual Type GetValueType()
return null;
}

public virtual void SetValueType(string type)
public virtual void SetValueType(string? type)
{
_proxy?.Set("VALUE", type?.ToUpper());
_proxy.Set("VALUE", type?.ToUpper());
}

public virtual ICalendarObject AssociatedObject
public virtual ICalendarObject? AssociatedObject
{
get => _associatedObject;
set
Expand All @@ -124,9 +126,9 @@ public virtual ICalendarObject AssociatedObject
}
}

public virtual Calendar Calendar => _associatedObject?.Calendar;
public virtual Calendar? Calendar => _associatedObject?.Calendar;

public virtual string Language
public virtual string? Language
{
get => Parameters.Get("LANGUAGE");
set => Parameters.Set("LANGUAGE", value);
Expand All @@ -149,7 +151,7 @@ public virtual void CopyFrom(ICopyable obj)
/// Creates a deep copy of the <see cref="T"/> object.
/// </summary>
/// <returns>The copy of the <see cref="T"/> object.</returns>
public virtual T Copy<T>()
public virtual T? Copy<T>()
{
var type = GetType();
var obj = Activator.CreateInstance(type, true) as ICopyable;
Expand Down
Loading
Loading